extend '-A / --abort' & '"skip": "abort"' functionality (#7891)

implement ascending by more than 1 level or
up to an extractor with a specific subcategory
This commit is contained in:
Mike Fährmann
2025-07-30 00:01:49 +02:00
parent 64de6605ce
commit 2eb5e52055
5 changed files with 70 additions and 23 deletions

View File

@@ -313,28 +313,51 @@ Type
* ``string``
Default
``true``
Example
* ``"abort:5"``
* ``"abort:5:2"``
* ``"abort:5:manga"``
* ``"terminate:3"``
Description
Controls the behavior when downloading files that have been
downloaded before, i.e. a file with the same filename already
exists or its ID is in a `download archive <extractor.*.archive_>`__.
* ``true``: Skip downloads
* ``false``: Overwrite already existing files
``true``
Skip downloads
``false``
Overwrite already existing files
* ``"abort"``: Stop the current extractor run
* ``"abort:N"``: Skip downloads and stop the current extractor run
after ``N`` consecutive skips
``"abort"``
Stop the current extractor
``"abort:N"``
Skip downloads and
stop the current extractor after ``N`` consecutive skips
``"abort:N:L"``
| Skip downloads and
stop the current extractor after ``N`` consecutive skips
| Ascend ``L`` levels in the extractor hierarchy
``"abort:N:SC"``
| Skip downloads and
stop the current extractor after ``N`` consecutive skips
| Ascend to an extractor with subcategory ``SC`` in the extractor hierarchy
* ``"terminate"``: Stop the current extractor run, including parent extractors
* ``"terminate:N"``: Skip downloads and stop the current extractor run,
including parent extractors, after ``N`` consecutive skips
``"terminate"``
Stop the current extractor, including parent extractors
``"terminate:N"``
Skip downloads and
stop the current extractor, including parent extractors,
after ``N`` consecutive skips
* ``"exit"``: Exit the program altogether
* ``"exit:N"``: Skip downloads and exit the program
after ``N`` consecutive skips
``"exit"``
Exit the program altogether
``"exit:N"``
Skip downloads and
exit the program after ``N`` consecutive skips
* ``"enumerate"``: Add an enumeration index to the beginning of the
filename extension (``file.1.ext``, ``file.2.ext``, etc.)
``"enumerate"``
Add an enumeration index to the beginning of the
filename extension (``file.1.ext``, ``file.2.ext``, etc.)
extractor.*.skip-filter

View File

@@ -48,7 +48,7 @@ def main():
if filename == "/O":
filename = "{filename}.{extension}"
elif filename.startswith("\\f"):
filename = "\f" + filename[2:]
filename = f"\f{filename[2:]}"
config.set((), "filename", filename)
if args.directory is not None:
config.set((), "base-directory", args.directory)
@@ -56,9 +56,9 @@ def main():
if args.postprocessors:
config.set((), "postprocessors", args.postprocessors)
if args.abort:
config.set((), "skip", "abort:" + str(args.abort))
config.set((), "skip", f"abort:{args.abort}")
if args.terminate:
config.set((), "skip", "terminate:" + str(args.terminate))
config.set((), "skip", f"terminate:{args.terminate}")
if args.cookies_from_browser:
browser, _, profile = args.cookies_from_browser.partition(":")
browser, _, keyring = browser.partition("+")

View File

@@ -160,6 +160,22 @@ class ControlException(GalleryDLException):
class StopExtraction(ControlException):
"""Stop data extraction"""
def __init__(self, target=None):
ControlException.__init__(self)
if target is None:
self.target = None
self.depth = 1
elif isinstance(target, int):
self.target = None
self.depth = target
elif target.isdecimal():
self.target = None
self.depth = int(target)
else:
self.target = target
self.depth = 128
class AbortExtraction(ExtractionError, ControlException):
"""Abort data extraction due to an error"""

View File

@@ -151,7 +151,10 @@ class Job():
try:
for msg in extractor:
self.dispatch(msg)
except exception.StopExtraction:
except exception.StopExtraction as exc:
if exc.depth > 1 and exc.target != extractor.__class__.subcategory:
exc.depth -= 1
raise
pass
except exception.AbortExtraction as exc:
log.error(exc.message)
@@ -509,7 +512,7 @@ class DownloadJob(Job):
if not self._skipftr or self._skipftr(pathfmt.kwdict):
self._skipcnt += 1
if self._skipcnt >= self._skipmax:
raise self._skipexc()
raise self._skipexc
def download(self, url):
"""Download 'url'"""
@@ -603,7 +606,8 @@ class DownloadJob(Job):
elif isinstance(skip, str):
skip, _, smax = skip.partition(":")
if skip == "abort":
self._skipexc = exception.StopExtraction
smax, _, sarg = smax.partition(":")
self._skipexc = exception.StopExtraction(sarg or None)
elif skip == "terminate":
self._skipexc = exception.TerminateExtraction
elif skip == "exit":

View File

@@ -664,14 +664,18 @@ def build_parser():
selection = parser.add_argument_group("Selection Options")
selection.add_argument(
"-A", "--abort",
dest="abort", metavar="N", type=int,
help=("Stop current extractor run "
"after N consecutive file downloads were skipped"),
dest="abort", metavar="N[:TARGET]",
help=("Stop current extractor(s) "
"after N consecutive file downloads were skipped. "
"Specify a TARGET to set how many levels to ascend or "
"to which subcategory to jump to. "
"Examples: '-A 3', '-A 3:2', '-A 3:manga'"),
)
selection.add_argument(
"-T", "--terminate",
dest="terminate", metavar="N", type=int,
help=("Stop current and parent extractor runs "
help=("Stop current & parent extractors "
"and proceed with the next input URL "
"after N consecutive file downloads were skipped"),
)
selection.add_argument(