mirror of
https://github.com/mikf/gallery-dl.git
synced 2024-11-25 12:12:34 +01:00
update PathFormat class
- change 'has_extension' from a simple flag/bool to a field that contains the original filename extension - rename 'keywords' to 'kwdict' and some other stuff as well - inline 'adjust_path()' - put enumeration index before filename extension (#306)
This commit is contained in:
parent
423f68f585
commit
0bb873757a
@ -114,7 +114,7 @@ class HttpDownloader(DownloaderBase):
|
|||||||
size = text.parse_int(size)
|
size = text.parse_int(size)
|
||||||
|
|
||||||
# set missing filename extension
|
# set missing filename extension
|
||||||
if not pathfmt.has_extension:
|
if not pathfmt.extension:
|
||||||
pathfmt.set_extension(self.get_extension(response))
|
pathfmt.set_extension(self.get_extension(response))
|
||||||
if pathfmt.exists():
|
if pathfmt.exists():
|
||||||
pathfmt.temppath = ""
|
pathfmt.temppath = ""
|
||||||
@ -153,7 +153,7 @@ class HttpDownloader(DownloaderBase):
|
|||||||
|
|
||||||
# check filename extension
|
# check filename extension
|
||||||
if self.adjust_extension:
|
if self.adjust_extension:
|
||||||
adj_ext = self.check_extension(file, pathfmt)
|
adj_ext = self.check_extension(file, pathfmt.extension)
|
||||||
if adj_ext:
|
if adj_ext:
|
||||||
pathfmt.set_extension(adj_ext)
|
pathfmt.set_extension(adj_ext)
|
||||||
|
|
||||||
@ -161,7 +161,7 @@ class HttpDownloader(DownloaderBase):
|
|||||||
|
|
||||||
self.downloading = False
|
self.downloading = False
|
||||||
if self.mtime:
|
if self.mtime:
|
||||||
pathfmt.keywords["_mtime"] = response.headers.get("Last-Modified")
|
pathfmt.kwdict["_mtime"] = response.headers.get("Last-Modified")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def receive(self, response, file):
|
def receive(self, response, file):
|
||||||
@ -197,9 +197,8 @@ class HttpDownloader(DownloaderBase):
|
|||||||
return "txt"
|
return "txt"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def check_extension(file, pathfmt):
|
def check_extension(file, extension):
|
||||||
"""Check filename extension against fileheader"""
|
"""Check filename extension against fileheader"""
|
||||||
extension = pathfmt.keywords["extension"]
|
|
||||||
if extension in FILETYPE_CHECK:
|
if extension in FILETYPE_CHECK:
|
||||||
file.seek(0)
|
file.seek(0)
|
||||||
header = file.read(8)
|
header = file.read(8)
|
||||||
|
@ -50,7 +50,7 @@ class YoutubeDLDownloader(DownloaderBase):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
if "entries" in info_dict:
|
if "entries" in info_dict:
|
||||||
index = pathfmt.keywords.get("_ytdl_index")
|
index = pathfmt.kwdict.get("_ytdl_index")
|
||||||
if index is None:
|
if index is None:
|
||||||
return self._download_playlist(pathfmt, info_dict)
|
return self._download_playlist(pathfmt, info_dict)
|
||||||
else:
|
else:
|
||||||
@ -59,7 +59,7 @@ class YoutubeDLDownloader(DownloaderBase):
|
|||||||
|
|
||||||
def _download_video(self, pathfmt, info_dict):
|
def _download_video(self, pathfmt, info_dict):
|
||||||
if "url" in info_dict:
|
if "url" in info_dict:
|
||||||
text.nameext_from_url(info_dict["url"], pathfmt.keywords)
|
text.nameext_from_url(info_dict["url"], pathfmt.kwdict)
|
||||||
pathfmt.set_extension(info_dict["ext"])
|
pathfmt.set_extension(info_dict["ext"])
|
||||||
if pathfmt.exists():
|
if pathfmt.exists():
|
||||||
pathfmt.temppath = ""
|
pathfmt.temppath = ""
|
||||||
|
@ -196,7 +196,7 @@ class DownloadJob(Job):
|
|||||||
archive = self.archive
|
archive = self.archive
|
||||||
|
|
||||||
# prepare download
|
# prepare download
|
||||||
pathfmt.set_keywords(keywords)
|
pathfmt.set_filename(keywords)
|
||||||
|
|
||||||
if postprocessors:
|
if postprocessors:
|
||||||
for pp in postprocessors:
|
for pp in postprocessors:
|
||||||
@ -364,7 +364,7 @@ class SimulationJob(DownloadJob):
|
|||||||
"""Simulate the extraction process without downloading anything"""
|
"""Simulate the extraction process without downloading anything"""
|
||||||
|
|
||||||
def handle_url(self, url, keywords, fallback=None):
|
def handle_url(self, url, keywords, fallback=None):
|
||||||
self.pathfmt.set_keywords(keywords)
|
self.pathfmt.set_filename(keywords)
|
||||||
self.out.skip(self.pathfmt.path)
|
self.out.skip(self.pathfmt.path)
|
||||||
if self.sleep:
|
if self.sleep:
|
||||||
time.sleep(self.sleep)
|
time.sleep(self.sleep)
|
||||||
|
@ -33,7 +33,7 @@ class ClassifyPP(PostProcessor):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def prepare(self, pathfmt):
|
def prepare(self, pathfmt):
|
||||||
ext = pathfmt.keywords.get("extension")
|
ext = pathfmt.extension
|
||||||
|
|
||||||
if ext in self.mapping:
|
if ext in self.mapping:
|
||||||
self._dir = pathfmt.realdirectory + os.sep + self.mapping[ext]
|
self._dir = pathfmt.realdirectory + os.sep + self.mapping[ext]
|
||||||
|
@ -36,15 +36,14 @@ class MetadataPP(PostProcessor):
|
|||||||
def run(self, pathfmt):
|
def run(self, pathfmt):
|
||||||
path = "{}.{}".format(pathfmt.realpath, self.extension)
|
path = "{}.{}".format(pathfmt.realpath, self.extension)
|
||||||
with open(path, "w", encoding="utf-8") as file:
|
with open(path, "w", encoding="utf-8") as file:
|
||||||
self.write(file, pathfmt)
|
self.write(file, pathfmt.kwdict)
|
||||||
|
|
||||||
def _write_custom(self, file, pathfmt):
|
def _write_custom(self, file, kwdict):
|
||||||
output = self.formatter.format_map(pathfmt.keywords)
|
output = self.formatter.format_map(kwdict)
|
||||||
file.write(output)
|
file.write(output)
|
||||||
|
|
||||||
def _write_tags(self, file, pathfmt):
|
def _write_tags(self, file, kwdict):
|
||||||
kwds = pathfmt.keywords
|
tags = kwdict.get("tags") or kwdict.get("tag_string")
|
||||||
tags = kwds.get("tags") or kwds.get("tag_string")
|
|
||||||
|
|
||||||
if not tags:
|
if not tags:
|
||||||
return
|
return
|
||||||
@ -58,8 +57,8 @@ class MetadataPP(PostProcessor):
|
|||||||
file.write("\n".join(tags))
|
file.write("\n".join(tags))
|
||||||
file.write("\n")
|
file.write("\n")
|
||||||
|
|
||||||
def _write_json(self, file, pathfmt):
|
def _write_json(self, file, kwdict):
|
||||||
util.dump_json(pathfmt.keywords, file, self.ascii, self.indent)
|
util.dump_json(kwdict, file, self.ascii, self.indent)
|
||||||
|
|
||||||
|
|
||||||
__postprocessor__ = MetadataPP
|
__postprocessor__ = MetadataPP
|
||||||
|
@ -19,9 +19,9 @@ class MtimePP(PostProcessor):
|
|||||||
self.key = options.get("key", "date")
|
self.key = options.get("key", "date")
|
||||||
|
|
||||||
def run(self, pathfmt):
|
def run(self, pathfmt):
|
||||||
mtime = pathfmt.keywords.get(self.key)
|
mtime = pathfmt.kwdict.get(self.key)
|
||||||
ts = getattr(mtime, "timestamp", None)
|
ts = getattr(mtime, "timestamp", None)
|
||||||
pathfmt.keywords["_mtime"] = ts() if ts else parse_int(mtime)
|
pathfmt.kwdict["_mtime"] = ts() if ts else parse_int(mtime)
|
||||||
|
|
||||||
|
|
||||||
__postprocessor__ = MtimePP
|
__postprocessor__ = MtimePP
|
||||||
|
@ -52,13 +52,13 @@ class UgoiraPP(PostProcessor):
|
|||||||
def prepare(self, pathfmt):
|
def prepare(self, pathfmt):
|
||||||
self._frames = None
|
self._frames = None
|
||||||
|
|
||||||
if pathfmt.keywords["extension"] != "zip":
|
if pathfmt.extension != "zip":
|
||||||
return
|
return
|
||||||
|
|
||||||
if "frames" in pathfmt.keywords:
|
if "frames" in pathfmt.kwdict:
|
||||||
self._frames = pathfmt.keywords["frames"]
|
self._frames = pathfmt.kwdict["frames"]
|
||||||
elif "pixiv_ugoira_frame_data" in pathfmt.keywords:
|
elif "pixiv_ugoira_frame_data" in pathfmt.kwdict:
|
||||||
self._frames = pathfmt.keywords["pixiv_ugoira_frame_data"]["data"]
|
self._frames = pathfmt.kwdict["pixiv_ugoira_frame_data"]["data"]
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -523,13 +523,12 @@ class PathFormat():
|
|||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
raise exception.FormatError(exc, "filename")
|
raise exception.FormatError(exc, "filename")
|
||||||
|
|
||||||
self.delete = False
|
|
||||||
self.has_extension = False
|
|
||||||
self.keywords = {}
|
|
||||||
self.filename = ""
|
|
||||||
self.directory = self.realdirectory = ""
|
self.directory = self.realdirectory = ""
|
||||||
|
self.filename = ""
|
||||||
|
self.extension = ""
|
||||||
|
self.kwdict = {}
|
||||||
|
self.delete = False
|
||||||
self.path = self.realpath = self.temppath = ""
|
self.path = self.realpath = self.temppath = ""
|
||||||
self.suffix = ""
|
|
||||||
|
|
||||||
self.basedirectory = expand_path(
|
self.basedirectory = expand_path(
|
||||||
extractor.config("base-directory", (".", "gallery-dl")))
|
extractor.config("base-directory", (".", "gallery-dl")))
|
||||||
@ -563,9 +562,9 @@ class PathFormat():
|
|||||||
|
|
||||||
def exists(self, archive=None):
|
def exists(self, archive=None):
|
||||||
"""Return True if the file exists on disk or in 'archive'"""
|
"""Return True if the file exists on disk or in 'archive'"""
|
||||||
if archive and archive.check(self.keywords):
|
if archive and archive.check(self.kwdict):
|
||||||
return self.fix_extension()
|
return self.fix_extension()
|
||||||
if self.has_extension and os.path.exists(self.realpath):
|
if self.extension and os.path.exists(self.realpath):
|
||||||
return self.check_file()
|
return self.check_file()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -576,71 +575,79 @@ class PathFormat():
|
|||||||
def _enum_file(self):
|
def _enum_file(self):
|
||||||
num = 1
|
num = 1
|
||||||
while True:
|
while True:
|
||||||
suffix = "." + str(num)
|
self.set_extension("{}.{}".format(num, self.extension), False)
|
||||||
rpath = self.realpath + suffix
|
if not os.path.exists(self.realpath):
|
||||||
if not os.path.exists(rpath):
|
|
||||||
self.path += suffix
|
|
||||||
self.realpath = rpath
|
|
||||||
self.suffix = suffix
|
|
||||||
return False
|
return False
|
||||||
num += 1
|
num += 1
|
||||||
|
|
||||||
def set_directory(self, keywords):
|
def set_directory(self, kwdict):
|
||||||
"""Build directory path and create it if necessary"""
|
"""Build directory path and create it if necessary"""
|
||||||
|
|
||||||
|
# Build path segments by applying 'kwdict' to directory format strings
|
||||||
try:
|
try:
|
||||||
segments = [
|
segments = [
|
||||||
self.clean_path(
|
self.clean_path(
|
||||||
Formatter(segment, self.kwdefault)
|
Formatter(segment, self.kwdefault)
|
||||||
.format_map(keywords).strip())
|
.format_map(kwdict).strip())
|
||||||
for segment in self.directory_fmt
|
for segment in self.directory_fmt
|
||||||
]
|
]
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
raise exception.FormatError(exc, "directory")
|
raise exception.FormatError(exc, "directory")
|
||||||
|
|
||||||
self.directory = os.path.join(
|
# Join path segements
|
||||||
self.basedirectory,
|
self.directory = os.path.join(self.basedirectory, *segments)
|
||||||
*segments
|
|
||||||
)
|
|
||||||
|
|
||||||
# remove trailing path separator;
|
# Remove trailing path separator;
|
||||||
# occurs if the last argument to os.path.join() is an empty string
|
# occurs if the last argument to os.path.join() is an empty string
|
||||||
if self.directory[-1] == os.sep:
|
if self.directory[-1] == os.sep:
|
||||||
self.directory = self.directory[:-1]
|
self.directory = self.directory[:-1]
|
||||||
|
|
||||||
self.realdirectory = self.adjust_path(self.directory)
|
# Enable longer-than-260-character paths on Windows
|
||||||
|
if os.name == "nt":
|
||||||
|
self.realdirectory = "\\\\?\\" + os.path.abspath(self.directory)
|
||||||
|
else:
|
||||||
|
self.realdirectory = self.directory
|
||||||
|
|
||||||
|
# Create directory tree
|
||||||
os.makedirs(self.realdirectory, exist_ok=True)
|
os.makedirs(self.realdirectory, exist_ok=True)
|
||||||
|
|
||||||
def set_keywords(self, keywords):
|
def set_filename(self, kwdict):
|
||||||
"""Set filename keywords"""
|
"""Set general filename data"""
|
||||||
self.keywords = keywords
|
self.kwdict = kwdict
|
||||||
self.temppath = self.suffix = ""
|
self.temppath = ""
|
||||||
self.has_extension = bool(keywords.get("extension"))
|
self.extension = kwdict["extension"]
|
||||||
if self.has_extension:
|
|
||||||
|
if self.extension:
|
||||||
self.build_path()
|
self.build_path()
|
||||||
|
|
||||||
def set_extension(self, extension, real=True):
|
def set_extension(self, extension, real=True):
|
||||||
"""Set the 'extension' keyword"""
|
"""Set filename extension"""
|
||||||
self.has_extension = real
|
if real:
|
||||||
self.keywords["extension"] = extension
|
self.extension = extension
|
||||||
|
self.kwdict["extension"] = extension
|
||||||
self.build_path()
|
self.build_path()
|
||||||
|
|
||||||
def fix_extension(self, _=None):
|
def fix_extension(self, _=None):
|
||||||
if not self.has_extension:
|
"""Fix filenames without a given filename extension"""
|
||||||
self.set_extension("")
|
if not self.extension:
|
||||||
|
self.set_extension("", False)
|
||||||
if self.path[-1] == ".":
|
if self.path[-1] == ".":
|
||||||
self.path = self.path[:-1]
|
self.path = self.path[:-1]
|
||||||
self.temppath = self.realpath = self.realpath[:-1]
|
self.temppath = self.realpath = self.realpath[:-1]
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def build_path(self):
|
def build_path(self):
|
||||||
"""Use filename-keywords and directory to build a full path"""
|
"""Use filename metadata and directory to build a full path"""
|
||||||
|
|
||||||
|
# Apply 'kwdict' to filename format string
|
||||||
try:
|
try:
|
||||||
self.filename = self.clean_path(
|
self.filename = self.clean_path(
|
||||||
self.formatter.format_map(self.keywords))
|
self.formatter.format_map(self.kwdict))
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
raise exception.FormatError(exc, "filename")
|
raise exception.FormatError(exc, "filename")
|
||||||
|
|
||||||
filename = os.sep + self.filename + self.suffix
|
# Combine directory and filename to full paths
|
||||||
|
filename = os.sep + self.filename
|
||||||
self.path = self.directory + filename
|
self.path = self.directory + filename
|
||||||
self.realpath = self.realdirectory + filename
|
self.realpath = self.realdirectory + filename
|
||||||
if not self.temppath:
|
if not self.temppath:
|
||||||
@ -648,7 +655,7 @@ class PathFormat():
|
|||||||
|
|
||||||
def part_enable(self, part_directory=None):
|
def part_enable(self, part_directory=None):
|
||||||
"""Enable .part file usage"""
|
"""Enable .part file usage"""
|
||||||
if self.has_extension:
|
if self.extension:
|
||||||
self.temppath += ".part"
|
self.temppath += ".part"
|
||||||
else:
|
else:
|
||||||
self.set_extension("part", False)
|
self.set_extension("part", False)
|
||||||
@ -674,16 +681,16 @@ class PathFormat():
|
|||||||
return
|
return
|
||||||
|
|
||||||
if self.temppath != self.realpath:
|
if self.temppath != self.realpath:
|
||||||
# move temp file to its actual location
|
# Move temp file to its actual location
|
||||||
try:
|
try:
|
||||||
os.replace(self.temppath, self.realpath)
|
os.replace(self.temppath, self.realpath)
|
||||||
except OSError:
|
except OSError:
|
||||||
shutil.copyfile(self.temppath, self.realpath)
|
shutil.copyfile(self.temppath, self.realpath)
|
||||||
os.unlink(self.temppath)
|
os.unlink(self.temppath)
|
||||||
|
|
||||||
if "_mtime" in self.keywords:
|
if "_mtime" in self.kwdict:
|
||||||
# set file modification time
|
# Set file modification time
|
||||||
mtime = self.keywords["_mtime"]
|
mtime = self.kwdict["_mtime"]
|
||||||
if mtime:
|
if mtime:
|
||||||
try:
|
try:
|
||||||
if isinstance(mtime, str):
|
if isinstance(mtime, str):
|
||||||
@ -692,11 +699,6 @@ class PathFormat():
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def adjust_path(path):
|
|
||||||
"""Enable longer-than-260-character paths on windows"""
|
|
||||||
return "\\\\?\\" + os.path.abspath(path) if os.name == "nt" else path
|
|
||||||
|
|
||||||
|
|
||||||
class DownloadArchive():
|
class DownloadArchive():
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ class TestDownloaderBase(unittest.TestCase):
|
|||||||
}
|
}
|
||||||
pathfmt = PathFormat(cls.extractor)
|
pathfmt = PathFormat(cls.extractor)
|
||||||
pathfmt.set_directory(kwdict)
|
pathfmt.set_directory(kwdict)
|
||||||
pathfmt.set_keywords(kwdict)
|
pathfmt.set_filename(kwdict)
|
||||||
|
|
||||||
if content:
|
if content:
|
||||||
mode = "w" + ("b" if isinstance(content, bytes) else "")
|
mode = "w" + ("b" if isinstance(content, bytes) else "")
|
||||||
@ -145,7 +145,7 @@ class TestDownloaderBase(unittest.TestCase):
|
|||||||
|
|
||||||
# test filename extension
|
# test filename extension
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
pathfmt.keywords["extension"],
|
pathfmt.extension,
|
||||||
expected_extension,
|
expected_extension,
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
|
@ -218,8 +218,8 @@ class TestPathfmt():
|
|||||||
self.hashobj = hashobj
|
self.hashobj = hashobj
|
||||||
self.path = ""
|
self.path = ""
|
||||||
self.size = 0
|
self.size = 0
|
||||||
self.keywords = {}
|
self.kwdict = {}
|
||||||
self.has_extension = True
|
self.extension = "jpg"
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
return self
|
return self
|
||||||
|
Loading…
Reference in New Issue
Block a user