initial 'signals-actions' implementation (#6582)
https://github.com/mikf/gallery-dl/issues/6582#issuecomment-2973285775 To stop gracefully after the current file finishes processing when Ctrl+C was pressed, or after the current post finishes processing when SIGUSR1 was received: { "signals-actions": { "SIGINT" : "file", "SIGUSR1": "post" } }
This commit is contained in:
@@ -11,7 +11,7 @@ import logging
|
||||
from . import version, config, option, output, extractor, job, util, exception
|
||||
|
||||
__author__ = "Mike Fährmann"
|
||||
__copyright__ = "Copyright 2014-2023 Mike Fährmann"
|
||||
__copyright__ = "Copyright 2014-2025 Mike Fährmann"
|
||||
__license__ = "GPLv2"
|
||||
__maintainer__ = "Mike Fährmann"
|
||||
__email__ = "mike_faehrmann@web.de"
|
||||
@@ -78,8 +78,7 @@ def main():
|
||||
output.configure_standard_streams()
|
||||
|
||||
# signals
|
||||
signals = config.get((), "signals-ignore")
|
||||
if signals:
|
||||
if signals := config.get((), "signals-ignore"):
|
||||
import signal
|
||||
if isinstance(signals, str):
|
||||
signals = signals.split(",")
|
||||
@@ -90,6 +89,19 @@ def main():
|
||||
else:
|
||||
signal.signal(signal_num, signal.SIG_IGN)
|
||||
|
||||
if signals := config.get((), "signals-actions"):
|
||||
import signal
|
||||
for signal_name, action in signals.items():
|
||||
signal_num = getattr(signal, signal_name, None)
|
||||
if signal_num is None:
|
||||
log.warning("signal '%s' is not defined", signal_name)
|
||||
else:
|
||||
def handler(signal_num, frame):
|
||||
signal_name = signal.Signals(signal_num).name
|
||||
output.stderr_write(f"{signal_name} received\n")
|
||||
util.FLAGS.__dict__[action.upper()] = "stop"
|
||||
signal.signal(signal_num, handler)
|
||||
|
||||
# enable ANSI escape sequences on Windows
|
||||
if util.WINDOWS and config.get(("output",), "ansi", output.COLORS):
|
||||
from ctypes import windll, wintypes, byref
|
||||
|
||||
@@ -28,6 +28,7 @@ from . import (
|
||||
)
|
||||
from .extractor.message import Message
|
||||
stdout_write = output.stdout_write
|
||||
FLAGS = util.FLAGS
|
||||
|
||||
|
||||
class Job():
|
||||
@@ -200,6 +201,8 @@ class Job():
|
||||
if self.pred_url(url, kwdict):
|
||||
self.update_kwdict(kwdict)
|
||||
self.handle_url(url, kwdict)
|
||||
if FLAGS.FILE is not None:
|
||||
FLAGS.FILE = FLAGS.process(FLAGS.FILE)
|
||||
|
||||
elif msg[0] == Message.Directory:
|
||||
self.update_kwdict(msg[1])
|
||||
@@ -212,6 +215,8 @@ class Job():
|
||||
if self.pred_queue(url, kwdict):
|
||||
self.update_kwdict(kwdict)
|
||||
self.handle_queue(url, kwdict)
|
||||
if FLAGS.CHILD is not None:
|
||||
FLAGS.CHILD = FLAGS.process(FLAGS.CHILD)
|
||||
|
||||
def handle_url(self, url, kwdict):
|
||||
"""Handle Message.Url"""
|
||||
@@ -390,6 +395,8 @@ class DownloadJob(Job):
|
||||
if "post-after" in self.hooks:
|
||||
for callback in self.hooks["post-after"]:
|
||||
callback(self.pathfmt)
|
||||
if FLAGS.POST is not None:
|
||||
FLAGS.POST = FLAGS.process(FLAGS.POST)
|
||||
self.pathfmt.set_directory(kwdict)
|
||||
if "post" in self.hooks:
|
||||
for callback in self.hooks["post"]:
|
||||
|
||||
@@ -722,6 +722,17 @@ class CustomNone():
|
||||
__repr__ = __str__
|
||||
|
||||
|
||||
class Flags():
|
||||
|
||||
def __init__(self):
|
||||
self.FILE = self.POST = self.CHILD = self.DOWNLOAD = None
|
||||
|
||||
def process(self, flag):
|
||||
if flag == "terminate":
|
||||
raise exception.TerminateExtraction()
|
||||
raise exception.StopExtraction()
|
||||
|
||||
|
||||
# v137.0 release of Firefox on 2025-04-01 has ordinal 739342
|
||||
# 735506 == 739342 - 137 * 28
|
||||
# v135.0 release of Chrome on 2025-04-01 has ordinal 739342
|
||||
@@ -737,6 +748,7 @@ re = text.re
|
||||
re_compile = text.re_compile
|
||||
|
||||
NONE = CustomNone()
|
||||
FLAGS = Flags()
|
||||
EPOCH = datetime.datetime(1970, 1, 1)
|
||||
SECOND = datetime.timedelta(0, 1)
|
||||
WINDOWS = (os.name == "nt")
|
||||
|
||||
Reference in New Issue
Block a user