From d37e7f4898002b2aaab8890bf4b13c63e011a735 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20F=C3=A4hrmann?= Date: Mon, 13 Feb 2023 13:33:42 +0100 Subject: [PATCH] add 'hooks' option Very much a work in progress. At the moment, it allows to - wait and restart an extractor (#3338) - change the exit code (#3630) - change the log level of a logging message based on the contents of a logging message --- gallery_dl/job.py | 15 +++++++++++++++ gallery_dl/output.py | 42 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/gallery_dl/job.py b/gallery_dl/job.py index 630d2c91..998de7a2 100644 --- a/gallery_dl/job.py +++ b/gallery_dl/job.py @@ -6,6 +6,7 @@ # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. +import re import sys import errno import logging @@ -32,6 +33,16 @@ class Job(): self.kwdict = {} self.status = 0 + hooks = extr.config("hooks") + if hooks: + if isinstance(hooks, dict): + hooks = hooks.items() + self._wrap_logger = self._wrap_logger_hooks + self._logger_hooks = [ + (re.compile(pattern).search, hook) + for pattern, hook in hooks + ] + path_proxy = output.PathfmtProxy(self) self._logger_extra = { "job" : self, @@ -202,6 +213,10 @@ class Job(): def _wrap_logger(self, logger): return output.LoggerAdapter(logger, self._logger_extra) + def _wrap_logger_hooks(self, logger): + return output.LoggerAdapterEx( + logger, self._logger_extra, self) + def _write_unsupported(self, url): if self.ulog: self.ulog.info(url) diff --git a/gallery_dl/output.py b/gallery_dl/output.py index 3017f857..8905b021 100644 --- a/gallery_dl/output.py +++ b/gallery_dl/output.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright 2015-2022 Mike Fährmann +# Copyright 2015-2023 Mike Fährmann # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as @@ -10,8 +10,9 @@ import os import sys import shutil import logging +import functools import unicodedata -from . import config, util, formatter +from . import config, util, formatter, exception # -------------------------------------------------------------------- @@ -23,7 +24,7 @@ LOG_LEVEL = logging.INFO class Logger(logging.Logger): - """Custom logger that includes extra info in log records""" + """Custom Logger that includes extra info in log records""" def makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None, sinfo=None, @@ -63,6 +64,41 @@ class LoggerAdapter(): self.logger._log(logging.ERROR, msg, args, **kwargs) +class LoggerAdapterEx(): + + def __init__(self, logger, extra, job): + self.logger = logger + self.extra = extra + self.job = job + + self.debug = functools.partial(self.log, logging.DEBUG) + self.info = functools.partial(self.log, logging.INFO) + self.warning = functools.partial(self.log, logging.WARNING) + self.error = functools.partial(self.log, logging.ERROR) + + def log(self, level, msg, *args, **kwargs): + if args: + msg = msg % args + args = None + + for search, action in self.job._logger_hooks: + match = search(msg) + if match: + if action == "wait+restart": + kwargs["extra"] = self.extra + self.logger._log(level, msg, args, **kwargs) + input("Press Enter to continue") + raise exception.RestartExtraction() + elif action.startswith("~"): + level = logging._nameToLevel[action[1:]] + elif action.startswith("|"): + self.job.status |= int(action[1:]) + + if self.logger.isEnabledFor(level): + kwargs["extra"] = self.extra + self.logger._log(level, msg, args, **kwargs) + + class PathfmtProxy(): __slots__ = ("job",)