Skip to content

Commit c5d63c7

Browse files
committed
Handle cancellable POET weights downloads
Adds explicit cancellation support for POET weight downloads end-to-end. The weights dialog now requests thread interruption when the window is closed during an active download, shows a cancelling status, and prevents immediate close until the worker finishes. The download worker now checks interruption requests inside the read loop, aborts with a cancellation error, and reliably removes partial `.part` files on failure, while also tightening request/open handling with a timeout and clearer variable naming.
1 parent d11a46e commit c5d63c7

2 files changed

Lines changed: 50 additions & 15 deletions

File tree

‎dlclivegui/gui/misc/weights_dialog.py‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,22 @@ def _download_cleanup(self) -> None:
163163
self.download_button.setEnabled(True)
164164
self.close_button.setEnabled(True)
165165

166+
def request_stop(self) -> None:
167+
thread = self._download_thread
168+
if thread is not None:
169+
thread.requestInterruption()
170+
166171
def reject(self) -> None:
167172
if self._download_thread is not None:
168173
return
169174

170175
super().reject()
176+
177+
def closeEvent(self, event) -> None:
178+
if self._download_thread is not None:
179+
self.request_stop()
180+
self.status_label.setText("Cancelling download...")
181+
event.ignore()
182+
return
183+
184+
super().closeEvent(event)

‎dlclivegui/services/inference/models/poet/weights.py‎

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import urllib.request
66
from pathlib import Path
77

8-
from PySide6.QtCore import QObject, Signal
8+
from PySide6.QtCore import QObject, QThread, Signal
99

1010
logger = logging.getLogger(__name__)
1111

@@ -29,37 +29,58 @@ def __init__(self, url: str, dest: Path):
2929
self.dest = dest
3030

3131
def run(self) -> None:
32+
tmp = None
33+
3234
try:
33-
self.dest.parent.mkdir(parents=True, exist_ok=True)
35+
self.dest.parent.mkdir(
36+
parents=True,
37+
exist_ok=True,
38+
)
39+
3440
if self.dest.is_file():
3541
self.progress.emit(100)
3642
self.finished.emit(str(self.dest))
3743
return
38-
tmp = self.dest.with_suffix(self.dest.suffix + ".part")
3944

40-
req = urllib.request.Request(self.url, headers={"User-Agent": "DLCLiveGUI"})
41-
with urllib.request.urlopen(req) as resp, open(tmp, "wb") as f:
42-
total = resp.length or 0
43-
done = 0
44-
chunk = 1024 * 256
45+
tmp = self.dest.with_suffix(self.dest.suffix + ".part")
46+
request = urllib.request.Request(
47+
self.url,
48+
headers={"User-Agent": "DLCLiveGUI"},
49+
)
50+
with (
51+
urllib.request.urlopen(
52+
request,
53+
timeout=30,
54+
) as response,
55+
tmp.open("wb") as output,
56+
):
57+
total = response.length or 0
58+
downloaded = 0
59+
chunk_size = 256 * 1024
4560

4661
while True:
47-
buf = resp.read(chunk)
48-
if not buf:
62+
if QThread.currentThread().isInterruptionRequested():
63+
raise RuntimeError("POET weights download was cancelled.")
64+
65+
chunk = response.read(chunk_size)
66+
if not chunk:
4967
break
50-
f.write(buf)
51-
done += len(buf)
68+
69+
output.write(chunk)
70+
downloaded += len(chunk)
71+
5272
if total > 0:
53-
self.progress.emit(int(done * 100 / total))
73+
self.progress.emit(int(downloaded * 100 / total))
5474

5575
os.replace(tmp, self.dest)
5676
self.progress.emit(100)
5777
self.finished.emit(str(self.dest))
5878

59-
except Exception as e:
79+
except Exception as exc:
6080
if tmp is not None:
6181
try:
6282
tmp.unlink(missing_ok=True)
6383
except OSError:
6484
logger.exception("Failed to remove partial POET weights.")
65-
self.error.emit(str(e))
85+
86+
self.error.emit(str(exc))

0 commit comments

Comments
 (0)