Browse Source

Drop asyncio experiment for now

unifiedWindowUI
Luke Murphy 4 years ago
parent
commit
c313126fdc
No known key found for this signature in database GPG Key ID: 5E2EF5A63E3718CC
  1. 97
      dropship.py
  2. 1
      requirements.txt

97
dropship.py

@ -1,13 +1,11 @@
"""Magic-Wormhole bundled up inside a PyGtk GUI.""" """Magic-Wormhole bundled up inside a PyGtk GUI."""
import asyncio
import logging import logging
import os import os
import subprocess
from pathlib import Path from pathlib import Path
from signal import SIGINT, SIGTERM from signal import SIGINT, SIGTERM
from subprocess import PIPE, Popen, TimeoutExpired
import asyncio_glib
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
@ -17,11 +15,9 @@ from gi.repository import Gdk as gdk
from gi.repository import GLib as glib from gi.repository import GLib as glib
from gi.repository import Gtk as gtk from gi.repository import Gtk as gtk
asyncio.set_event_loop_policy(asyncio_glib.GLibEventLoopPolicy())
logging.basicConfig(level=os.environ.get("LOGLEVEL", "INFO")) logging.basicConfig(level=os.environ.get("LOGLEVEL", "INFO"))
log = logging.getLogger("dropship") log = logging.getLogger("dropship")
loop = asyncio.get_event_loop()
AUTO_CLIP_COPY_SIZE = -1 AUTO_CLIP_COPY_SIZE = -1
@ -29,10 +25,11 @@ AUTO_CLIP_COPY_SIZE = -1
class PendingTransfer: class PendingTransfer:
"""A wormhole send waiting for a wormhole receive.""" """A wormhole send waiting for a wormhole receive."""
def __init__(self, code, fpath): def __init__(self, code, fpath, process):
"""Object initialisation.""" """Object initialisation."""
self.fpath = fpath self.fpath = fpath
self.code = code self.code = code
self.process = process
class DropShip: class DropShip:
@ -46,7 +43,6 @@ class DropShip:
self.clipboard = gtk.Clipboard.get(gdk.SELECTION_CLIPBOARD) self.clipboard = gtk.Clipboard.get(gdk.SELECTION_CLIPBOARD)
self._running = loop.create_future()
self._pending = [] self._pending = []
self.init_glade() self.init_glade()
@ -73,7 +69,7 @@ class DropShip:
"""Initialise the Main GUI window.""" """Initialise the Main GUI window."""
self.main_window_id = "mainWindow" self.main_window_id = "mainWindow"
self.window = self.builder.get_object(self.main_window_id) self.window = self.builder.get_object(self.main_window_id)
self.window.connect("delete-event", self.on_quit) self.window.connect("delete-event", gtk.main_quit)
self.window.show() self.window.show()
def init_ui_elements(self): def init_ui_elements(self):
@ -115,7 +111,7 @@ class DropShip:
if len(files) == 1: if len(files) == 1:
fpath = str(Path(files[0].replace("file://", ""))) fpath = str(Path(files[0].replace("file://", "")))
print(fpath, type(fpath)) print(fpath, type(fpath))
self.schedule(self.wormhole_send(self, fpath)) self.wormhole_send(self, fpath)
self.drop_label.set_text("Sending..") self.drop_label.set_text("Sending..")
self.drop_spinner.start() self.drop_spinner.start()
@ -126,50 +122,28 @@ class DropShip:
"""Handler for adding files with system interface""" """Handler for adding files with system interface"""
response = self.file_chooser.run() response = self.file_chooser.run()
if response == gtk.ResponseType.OK: if response == gtk.ResponseType.OK:
self.schedule(
self.wormhole_send(self, self.file_chooser.get_filenames()[0]) self.wormhole_send(self, self.file_chooser.get_filenames()[0])
)
elif response == gtk.ResponseType.CANCEL: elif response == gtk.ResponseType.CANCEL:
# TODO(roel) something isn't right here.. maybe we need to initialize it every time we run it. # TODO(roel) something isn't right here.. maybe we need to initialize it every time we run it.
print("Cancel clicked") print("Cancel clicked")
self.file_chooser.destroy() self.file_chooser.destroy()
def read_wormhole_send_code(self, process):
"""Read wormhole send code from command-line output."""
process.stderr.readline() # NOTE(decentral1se): skip first line
code_line = process.stderr.readline()
return code_line.split()[-1].decode("utf-8")
def on_recv(self, entry): def on_recv(self, entry):
"""Handler for receiving transfers.""" """Handler for receiving transfers."""
code = entry.get_text() code = entry.get_text()
self.schedule(self.wormhole_recv(self, code)) self.wormhole_recv(self, code)
def on_quit(self, *args, **kwargs):
"""Quit the program."""
self.window.close()
self._running.set_result(None)
def schedule(self, function):
"""Schedule a task on the event loop."""
loop.call_soon_threadsafe(asyncio.ensure_future, function)
async def read_lines(self, stream, pattern):
"""Read stdout from a command and match lines."""
# TODO(decentral1se): if pattern doesnt match, trapped forever
while True:
line = await stream.readline()
decoded = line.decode("utf-8").strip()
if pattern in decoded:
return decoded
async def wormhole_send(self, widget, fpath):
"""Run `wormhole send` on a local file path."""
process = await asyncio.create_subprocess_exec(
"wormhole",
"send",
"--hide-progress",
fpath,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
)
line = await self.read_lines(process.stderr, "wormhole receive") def wormhole_send(self, widget, fpath):
code = line.split()[-1] """Run `wormhole send` on a local file path."""
command = ["wormhole", "send", fpath]
process = Popen(command, stderr=PIPE)
code = self.read_wormhole_send_code(process)
self.drop_label.set_selectable(True) self.drop_label.set_selectable(True)
self.drop_label.set_text(code) self.drop_label.set_text(code)
@ -177,38 +151,15 @@ class DropShip:
self.clipboard.set_text(code, AUTO_CLIP_COPY_SIZE) self.clipboard.set_text(code, AUTO_CLIP_COPY_SIZE)
self._pending.append(PendingTransfer(code, fpath)) self._pending.append(PendingTransfer(code, fpath, process))
await process.wait() def wormhole_recv(self, widget, code):
async def wormhole_recv(self, widget, code):
"""Run `wormhole receive` with a pending transfer code.""" """Run `wormhole receive` with a pending transfer code."""
process = await asyncio.create_subprocess_exec( command = ["wormhole", "receive", "--accept-file", code]
"wormhole", process = Popen(command, stderr=PIPE)
"receive", process.communicate()
"--accept-file",
"--hide-progress",
code,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
)
await process.wait()
async def main():
"""The application entrypoint."""
try:
dropship = DropShip()
await dropship._running
except asyncio.CancelledError:
pass
if __name__ == "__main__": if __name__ == "__main__":
try: DropShip()
main_task = asyncio.ensure_future(main()) gtk.main()
loop.add_signal_handler(SIGINT, main_task.cancel)
loop.add_signal_handler(SIGTERM, main_task.cancel)
loop.run_until_complete(main_task)
finally:
loop.close()

1
requirements.txt

@ -1,4 +1,3 @@
-e git+https://github.com/decentral1se/asyncio-glib#egg=asyncio-glib
PyGObject==3.36.1 PyGObject==3.36.1
PyInstaller==3.6 PyInstaller==3.6
magic-wormhole==0.12.0 magic-wormhole==0.12.0

Loading…
Cancel
Save