Workable pending transfer logic implementation!
With logging.
This commit is contained in:
parent
84865c68af
commit
86f81a6122
7
dropship/constant.py
Normal file
7
dropship/constant.py
Normal file
@ -0,0 +1,7 @@
|
||||
from pathlib import Path
|
||||
|
||||
_CWD = Path(__file__).absolute().parent
|
||||
|
||||
UI_DIR = f"{_CWD}/ui"
|
||||
|
||||
DEFAULT_DROP_LABEL = "Drag a file to send"
|
@ -1,9 +1,8 @@
|
||||
from os.path import basename
|
||||
from pathlib import Path
|
||||
from subprocess import PIPE
|
||||
|
||||
from gi import require_version
|
||||
from trio import open_process, run_process
|
||||
from trio import CancelScope, open_process, run_process
|
||||
|
||||
from dropship import log
|
||||
|
||||
@ -12,9 +11,11 @@ require_version("Gdk", "3.0")
|
||||
|
||||
from gi.repository import Gdk, GLib, Gtk
|
||||
|
||||
from dropship import log
|
||||
from dropship.constant import UI_DIR
|
||||
from dropship.transfer import PendingTransfer
|
||||
from dropship.ui_templates import PendingTransferRow
|
||||
|
||||
CWD = Path(__file__).absolute().parent
|
||||
from dropship.wormhole import wormhole_recv, wormhole_send
|
||||
|
||||
|
||||
class DropShip:
|
||||
@ -22,8 +23,8 @@ class DropShip:
|
||||
|
||||
def __init__(self, nursery):
|
||||
"""Object initialisation."""
|
||||
self.GLADE_FILE = f"{CWD}/ui/dropship.ui"
|
||||
self.CSS_FILE = f"{CWD}/ui/dropship.css"
|
||||
self.GLADE_FILE = f"{UI_DIR}/dropship.ui"
|
||||
self.CSS_FILE = f"{UI_DIR}/dropship.css"
|
||||
|
||||
self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
|
||||
self.nursery = nursery
|
||||
@ -95,20 +96,20 @@ class DropShip:
|
||||
self.files_to_send = files
|
||||
if len(files) == 1:
|
||||
fpath = files[0].replace("file://", "")
|
||||
self.nursery.start_soon(self.wormhole_send, fpath)
|
||||
self.nursery.start_soon(self.send, fpath)
|
||||
else:
|
||||
log.info("Multiple file sending coming soon ™")
|
||||
|
||||
def on_recv(self, entry):
|
||||
"""Handler for receiving transfers."""
|
||||
self.nursery.start_soon(self.wormhole_recv, entry.get_text())
|
||||
self.nursery.start_soon(self.receive, entry.get_text())
|
||||
|
||||
def add_files(self, widget, event):
|
||||
"""Handler for adding files with system interface"""
|
||||
response = self.file_chooser.run()
|
||||
if response == Gtk.ResponseType.OK:
|
||||
fpath = self.file_chooser.get_filenames()[0]
|
||||
self.nursery.start_soon(self.wormhole_send, fpath)
|
||||
self.nursery.start_soon(self.send, fpath)
|
||||
self.file_chooser.hide()
|
||||
|
||||
def _send_spinner_on(self):
|
||||
@ -128,23 +129,27 @@ class DropShip:
|
||||
self.drop_spinner.set_vexpand(False)
|
||||
self.drop_spinner.set_visible(False)
|
||||
|
||||
def _create_pending_transfer(self, fpath, code):
|
||||
def _create_pending_transfer(self, fpath, code, scope):
|
||||
"""Create a new pending transfer."""
|
||||
pending = PendingTransferRow(basename(fpath), code)
|
||||
self.pending_transfers_list.insert(pending, -1)
|
||||
transfer = PendingTransfer(fpath, code, scope)
|
||||
template = PendingTransferRow(transfer, self)
|
||||
self.pending_transfers_list.insert(template, -1)
|
||||
|
||||
async def wormhole_send(self, fpath):
|
||||
"""Run `wormhole send` on a local file path."""
|
||||
def _remove_pending_transfer(self, code):
|
||||
"""Remove pending transfer."""
|
||||
for pending_transfer in self.pending_transfers_list:
|
||||
if pending_transfer.code == code:
|
||||
pending_transfer.cancel()
|
||||
|
||||
async def send(self, fpath):
|
||||
self._send_spinner_on()
|
||||
process = await open_process(["wormhole", "send", fpath], stderr=PIPE)
|
||||
output = await process.stderr.receive_some()
|
||||
code = output.decode().split()[-1]
|
||||
self._create_pending_transfer(fpath, code)
|
||||
code, scope = await self.nursery.start(wormhole_send, fpath)
|
||||
self._create_pending_transfer(fpath, code, scope)
|
||||
self.clipboard.set_text(code, -1)
|
||||
self._send_spinner_off(code)
|
||||
await process.wait()
|
||||
log.info(f"send: successfully initiated transfer send ({code})")
|
||||
|
||||
async def wormhole_recv(self, code):
|
||||
"""Run `wormhole receive` with a pending transfer code."""
|
||||
command = ["wormhole", "receive", "--accept-file", code]
|
||||
await run_process(command, stderr=PIPE)
|
||||
async def receive(self, code):
|
||||
await self.nursery.start(wormhole_recv, code)
|
||||
self._remove_pending_transfer(code)
|
||||
log.info(f"receive: successfully received transfer ({code})")
|
||||
|
35
dropship/transfer.py
Normal file
35
dropship/transfer.py
Normal file
@ -0,0 +1,35 @@
|
||||
from os.path import basename, getsize
|
||||
|
||||
|
||||
class PendingTransfer:
|
||||
"""A pending transfer context and config."""
|
||||
|
||||
def __init__(self, fpath, code, scope):
|
||||
self.fpath = fpath
|
||||
self.code = code
|
||||
self.scope = scope
|
||||
|
||||
@property
|
||||
def fname(self):
|
||||
"""Filename being transferred."""
|
||||
return basename(self.fpath)
|
||||
|
||||
@property
|
||||
def size(self):
|
||||
"""Filename size."""
|
||||
return self._human_readable_size(getsize(self.fpath))
|
||||
|
||||
def cancel(self):
|
||||
"""Cancel the transfer."""
|
||||
self.scope.cancel()
|
||||
|
||||
def _human_readable_size(self, num, suffix="B"):
|
||||
"""Convert file size to human readable format.
|
||||
|
||||
Thanks Fred. See https://stackoverflow.com/a/1094933.
|
||||
"""
|
||||
for unit in ["", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"]:
|
||||
if abs(num) < 1024.0:
|
||||
return "%3.1f%s%s" % (num, unit, suffix)
|
||||
num /= 1024.0
|
||||
return "%.1f%s%s" % (num, "Yi", suffix)
|
@ -6,41 +6,51 @@ gi.require_version("Gtk", "3.0")
|
||||
|
||||
from gi.repository import Gdk, GLib, Gtk
|
||||
|
||||
CWD = Path(__file__).absolute().parent
|
||||
from dropship import log
|
||||
from dropship.constant import DEFAULT_DROP_LABEL, UI_DIR
|
||||
|
||||
|
||||
@Gtk.Template.from_file(f"{CWD}/ui/pendingTransferRow.ui")
|
||||
@Gtk.Template.from_file(f"{UI_DIR}/pendingTransferRow.ui")
|
||||
class PendingTransferRow(Gtk.ListBoxRow):
|
||||
# Note(decentral1se): must match ui/pendingTransferRow.ui name
|
||||
__gtype_name__ = "pendingTransferRow"
|
||||
|
||||
fileNameLabel = Gtk.Template.Child()
|
||||
fileNameMetadata = Gtk.Template.Child()
|
||||
transferCodeButton = Gtk.Template.Child()
|
||||
cancelTransfer = Gtk.Template.Child()
|
||||
pendingTransferRow = Gtk.Template.Child()
|
||||
|
||||
def __init__(self, fileName, transferCode, *args, **kwargs):
|
||||
def __init__(self, transfer, parent, *args, **kwargs):
|
||||
Gtk.ListBoxRow.__init__(self, *args, **kwargs)
|
||||
self.fileNameLabel.set_text(fileName)
|
||||
self.transferCodeButton.set_label(transferCode)
|
||||
self.transfer = transfer
|
||||
self.parent = parent
|
||||
self.fileNameLabel.set_text(self.transfer.fname)
|
||||
self.fileNameMetadata.set_text(self.transfer.size)
|
||||
self.transferCodeButton.set_label(self.transfer.code)
|
||||
|
||||
@property
|
||||
def code(self):
|
||||
"""Retrieve code of underyling transfer."""
|
||||
return self.transfer.code
|
||||
|
||||
@Gtk.Template.Callback("copy_transfer_code")
|
||||
def copy_transfer_code(self, widget):
|
||||
"""
|
||||
what to do when we press the button:
|
||||
copy the code again to clipboard
|
||||
"""
|
||||
print("click")
|
||||
"""Copy transfer code to clipboard."""
|
||||
code = widget.get_label()
|
||||
|
||||
clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
|
||||
clipboard.set_text(code, -1) # -1 is auto-size
|
||||
|
||||
@Gtk.Template.Callback("cancel_transfer")
|
||||
def cancel_transfer(self, widget):
|
||||
"""
|
||||
cancel the transfer
|
||||
destroy thread
|
||||
remove the object from the list
|
||||
"""
|
||||
print("poof!")
|
||||
"""Callback entrypoint for transfer cancellation."""
|
||||
self.cancel()
|
||||
|
||||
def cancel(self):
|
||||
"""Internal programmatic API for transfer cancellation."""
|
||||
self.transfer.cancel()
|
||||
self.pendingTransferRow.destroy()
|
||||
self.parent.drop_label.set_text(DEFAULT_DROP_LABEL)
|
||||
self.parent.drop_label.set_selectable(False)
|
||||
log.info(
|
||||
f"PendingTransferRow: successfully cancelled transfer ({self.transfer.code})"
|
||||
)
|
||||
|
37
dropship/wormhole.py
Normal file
37
dropship/wormhole.py
Normal file
@ -0,0 +1,37 @@
|
||||
from subprocess import PIPE
|
||||
|
||||
from trio import TASK_STATUS_IGNORED, CancelScope, open_process, run_process
|
||||
|
||||
from dropship import log
|
||||
|
||||
|
||||
async def wormhole_send(fpath, task_status=TASK_STATUS_IGNORED):
|
||||
"""Run `wormhole send` on a local file path."""
|
||||
with CancelScope() as scope:
|
||||
command = ["wormhole", "send", fpath]
|
||||
process = await open_process(command, stderr=PIPE)
|
||||
output = await process.stderr.receive_some()
|
||||
code = output.decode().split()[-1]
|
||||
task_status.started((code, scope,))
|
||||
log.info(f"wormhole_send: now waiting for other side ({code})")
|
||||
await process.wait()
|
||||
log.info(f"wormhole_send: succesfully transfered ({code})")
|
||||
|
||||
if scope.cancel_called:
|
||||
process.terminate()
|
||||
log.info(f"wormhole_send: succesfully terminated process ({code})")
|
||||
|
||||
|
||||
async def wormhole_recv(code, task_status=TASK_STATUS_IGNORED):
|
||||
"""Run `wormhole receive` on a pending transfer code."""
|
||||
with CancelScope() as scope:
|
||||
command = ["wormhole", "receive", "--accept-file", code]
|
||||
process = await open_process(command, stderr=PIPE)
|
||||
task_status.started((scope,))
|
||||
log.info(f"wormhole_recv: now starting receiving process ({code})")
|
||||
await process.wait()
|
||||
log.info(f"wormhole_recv: succesfully received ({code})")
|
||||
|
||||
if scope.cancel_called:
|
||||
process.terminate()
|
||||
log.info(f"wormhole_recv: succesfully terminated process ({code})")
|
Loading…
Reference in New Issue
Block a user