implement conditional directories (#1394)

They work the same way as conditional filenames (84d2e640), e.g.

"directory": {
    "score >= 20": ["high score"],
    "score >= 5" : ["mid score"],
    ""           : ["{category}", "default"]
}
This commit is contained in:
Mike Fährmann
2021-06-20 19:44:12 +02:00
parent ee1064a2b2
commit fd00d47116
4 changed files with 76 additions and 27 deletions

View File

@@ -1,5 +1,7 @@
# Changelog # Changelog
## Unreleased
## 1.18.0 - 2021-06-19 ## 1.18.0 - 2021-06-19
### Additions ### Additions
- [foolfuuka] support `archive.wakarimasen.moe` ([#1595](https://github.com/mikf/gallery-dl/issues/1595)) - [foolfuuka] support `archive.wakarimasen.moe` ([#1595](https://github.com/mikf/gallery-dl/issues/1595))

View File

@@ -60,7 +60,7 @@ extractor.*.filename
Type Type
``string`` or ``object`` ``string`` or ``object``
Example Example
* .. code:: * .. code:: json
"{manga}_c{chapter}_{page:>03}.{extension}" "{manga}_c{chapter}_{page:>03}.{extension}"
@@ -115,11 +115,25 @@ Description
extractor.*.directory extractor.*.directory
--------------------- ---------------------
Type Type
``list`` of ``strings`` ``list`` of ``strings`` or ``object``
Example Example
``["{category}", "{manga}", "c{chapter} - {title}"]`` * .. code:: json
["{category}", "{manga}", "c{chapter} - {title}"]
* .. code:: json
{
"'nature' in content": ["Nature Pictures"],
"retweet_id != 0" : ["{category}", "{user[name]}", "Retweets"],
"" : ["{category}", "{user[name]}"]
}
Description Description
A list of `format strings`_ for the resulting target directory. A list of `format strings`_ to build target directory paths with.
If this is an ``object``, it must contain Python expressions mapping to the
list of format strings to use.
Each individual string in such a list represents a single path Each individual string in such a list represents a single path
segment, which will be joined together and appended to the segment, which will be joined together and appended to the

View File

@@ -777,9 +777,20 @@ class PathFormat():
raise exception.FilenameFormatError(exc) raise exception.FilenameFormatError(exc)
directory_fmt = config("directory") directory_fmt = config("directory")
if directory_fmt is None:
directory_fmt = extractor.directory_fmt
try: try:
if directory_fmt is None:
directory_fmt = extractor.directory_fmt
elif isinstance(directory_fmt, dict):
self.directory_conditions = [
(compile_expression(expr), [
Formatter(fmt, kwdefault).format_map
for fmt in fmts
])
for expr, fmts in directory_fmt.items() if expr
]
self.build_directory = self.build_directory_conditional
directory_fmt = directory_fmt.get("", extractor.directory_fmt)
self.directory_formatters = [ self.directory_formatters = [
Formatter(dirfmt, kwdefault).format_map Formatter(dirfmt, kwdefault).format_map
for dirfmt in directory_fmt for dirfmt in directory_fmt
@@ -870,29 +881,14 @@ class PathFormat():
def set_directory(self, kwdict): def set_directory(self, kwdict):
"""Build directory path and create it if necessary""" """Build directory path and create it if necessary"""
self.kwdict = kwdict self.kwdict = kwdict
# Build path segments by applying 'kwdict' to directory format strings
segments = []
append = segments.append
try:
for formatter in self.directory_formatters:
segment = formatter(kwdict).strip()
if WINDOWS:
# remove trailing dots and spaces (#647)
segment = segment.rstrip(". ")
if segment:
append(self.clean_segment(segment))
except Exception as exc:
raise exception.DirectoryFormatError(exc)
# Join path segments
sep = os.sep sep = os.sep
directory = self.clean_path(self.basedirectory + sep.join(segments))
# Ensure 'directory' ends with a path separator segments = self.build_directory(kwdict)
if segments: if segments:
directory += sep self.directory = directory = self.clean_path(
self.directory = directory self.basedirectory + sep.join(segments) + sep)
else:
self.directory = directory = self.clean_path(self.basedirectory)
if WINDOWS: if WINDOWS:
# Enable longer-than-260-character paths on Windows # Enable longer-than-260-character paths on Windows
@@ -956,6 +952,43 @@ class PathFormat():
except Exception as exc: except Exception as exc:
raise exception.FilenameFormatError(exc) raise exception.FilenameFormatError(exc)
def build_directory(self, kwdict):
"""Apply 'kwdict' to directory format strings"""
segments = []
append = segments.append
try:
for formatter in self.directory_formatters:
segment = formatter(kwdict).strip()
if WINDOWS:
# remove trailing dots and spaces (#647)
segment = segment.rstrip(". ")
if segment:
append(self.clean_segment(segment))
return segments
except Exception as exc:
raise exception.DirectoryFormatError(exc)
def build_directory_conditional(self, kwdict):
segments = []
append = segments.append
try:
for condition, formatters in self.directory_conditions:
if condition(kwdict):
break
else:
formatters = self.directory_formatters
for formatter in formatters:
segment = formatter(kwdict).strip()
if WINDOWS:
segment = segment.rstrip(". ")
if segment:
append(self.clean_segment(segment))
return segments
except Exception as exc:
raise exception.DirectoryFormatError(exc)
def build_path(self): def build_path(self):
"""Combine directory and filename to full paths""" """Combine directory and filename to full paths"""
if self._create_directory: if self._create_directory:

View File

@@ -6,4 +6,4 @@
# it under the terms of the GNU General Public License version 2 as # it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation. # published by the Free Software Foundation.
__version__ = "1.18.0" __version__ = "1.18.1-dev"