all tests passing, lint 10, should test dry-run arg

This commit is contained in:
jbannon 2022-07-02 18:11:29 +00:00
parent 179540093c
commit 685ea60607
7 changed files with 92 additions and 46 deletions

View file

@ -100,8 +100,7 @@ class YoutubeMergePlaylistDownloader(
}, },
) )
@classmethod def _add_chapters(self, merged_video: YoutubeVideo) -> None:
def _add_chapters(cls, merged_video: YoutubeVideo) -> None:
titles: List[str] = [] titles: List[str] = []
timestamps: List[Timestamp] = [] timestamps: List[Timestamp] = []
@ -112,6 +111,8 @@ class YoutubeMergePlaylistDownloader(
current_timestamp_sec += video_entry["duration"] current_timestamp_sec += video_entry["duration"]
# TODO: return chapter metadata here
if not self.is_dry_run:
add_ffmpeg_metadata( add_ffmpeg_metadata(
file_path=merged_video.get_download_file_path(), file_path=merged_video.get_download_file_path(),
chapters=Chapters(timestamps=timestamps, titles=titles), chapters=Chapters(timestamps=timestamps, titles=titles),
@ -130,7 +131,11 @@ class YoutubeMergePlaylistDownloader(
entry_dict["duration"] = sum( entry_dict["duration"] = sum(
playlist_entry["duration"] for playlist_entry in entry_dict["entries"] playlist_entry["duration"] for playlist_entry in entry_dict["entries"]
) )
entry_dict["ext"] = entry_dict["requested_downloads"][0]["ext"] entry_dict["ext"] = (
entry_dict["requested_downloads"][0]["ext"]
if "requested_downloads" in entry_dict
else "mkv"
)
return YoutubeVideo(entry_dict=entry_dict, working_directory=self.working_directory) return YoutubeVideo(entry_dict=entry_dict, working_directory=self.working_directory)
def download(self) -> List[YoutubeVideo]: def download(self) -> List[YoutubeVideo]:

View file

@ -155,12 +155,10 @@ class YoutubeSplitVideoDownloader(
for idx, title in enumerate(chapters.titles): for idx, title in enumerate(chapters.titles):
new_uid = _split_video_uid(source_uid=entry.uid, idx=idx) new_uid = _split_video_uid(source_uid=entry.uid, idx=idx)
if not self.is_dry_run:
# Get the input/output file paths # Get the input/output file paths
input_file = entry.get_download_file_path() input_file = entry.get_download_file_path()
output_file = str(Path(self.working_directory) / f"{new_uid}.{entry.ext}") output_file = str(Path(self.working_directory) / f"{new_uid}.{entry.ext}")
output_thumbnail_file = str(
Path(self.working_directory) / f"{new_uid}.{entry.thumbnail_ext}"
)
# Run ffmpeg to create the split the video # Run ffmpeg to create the split the video
FFMPEG.run( FFMPEG.run(
@ -171,10 +169,12 @@ class YoutubeSplitVideoDownloader(
idx=idx, idx=idx,
) )
) )
# Copy the thumbnail
# Copy the original vid thumbnail to the working directory with the new uid. This so
# downstream logic thinks this split video has its own thumbnail
FileHandler.copy( FileHandler.copy(
src_file_path=entry.get_download_thumbnail_path(), src_file_path=entry.get_download_thumbnail_path(),
dst_file_path=output_thumbnail_file, dst_file_path=Path(self.working_directory) / f"{new_uid}.{entry.thumbnail_ext}",
) )
# Format the split video as a YoutubePlaylistVideo # Format the split video as a YoutubePlaylistVideo

View file

@ -4,6 +4,7 @@ import os
import shutil import shutil
from pathlib import Path from pathlib import Path
from typing import List from typing import List
from typing import Optional
from typing import Tuple from typing import Tuple
from typing import Type from typing import Type
@ -19,6 +20,7 @@ from ytdl_sub.entries.entry import Entry
from ytdl_sub.plugins.plugin import Plugin from ytdl_sub.plugins.plugin import Plugin
from ytdl_sub.plugins.plugin import PluginOptions from ytdl_sub.plugins.plugin import PluginOptions
from ytdl_sub.utils.file_handler import FileHandlerTransactionLog from ytdl_sub.utils.file_handler import FileHandlerTransactionLog
from ytdl_sub.utils.file_handler import FileMetadata
from ytdl_sub.utils.thumbnail import convert_download_thumbnail from ytdl_sub.utils.thumbnail import convert_download_thumbnail
from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive
@ -145,7 +147,9 @@ class Subscription:
and self.downloader_class.supports_download_archive and self.downloader_class.supports_download_archive
) )
def _copy_entry_files_to_output_directory(self, entry: Entry): def _copy_entry_files_to_output_directory(
self, entry: Entry, entry_metadata: Optional[FileMetadata] = None
):
""" """
Helper function to move the media file and optionally thumbnail file to the output directory Helper function to move the media file and optionally thumbnail file to the output directory
for a single entry. for a single entry.
@ -154,13 +158,18 @@ class Subscription:
---------- ----------
entry: entry:
The entry with files to move The entry with files to move
entry_metadata
Optional. Metadata to record to the transaction log for this entry
""" """
# Move the file after all direct file modifications are complete # Move the file after all direct file modifications are complete
output_file_name = self.overrides.apply_formatter( output_file_name = self.overrides.apply_formatter(
formatter=self.output_options.file_name, entry=entry formatter=self.output_options.file_name, entry=entry
) )
self._enhanced_download_archive.save_file_to_output_directory( self._enhanced_download_archive.save_file_to_output_directory(
file_name=entry.get_download_file_name(), output_file_name=output_file_name, entry=entry file_name=entry.get_download_file_name(),
file_metadata=entry_metadata,
output_file_name=output_file_name,
entry=entry,
) )
if self.output_options.thumbnail_name: if self.output_options.thumbnail_name:
@ -257,17 +266,19 @@ class Subscription:
ytdl_options=ytdl_options, ytdl_options=ytdl_options,
) )
entries = downloader.download() for entry in downloader.download():
# TODO: Add entry metadata from the downloader.download function
entry_metadata = FileMetadata()
for plugin in plugins: for plugin in plugins:
for entry in entries: entry_metadata.extend(plugin.post_process_entry(entry))
plugin.post_process_entry(entry)
plugin.post_process_subscription() self._copy_entry_files_to_output_directory(
entry=entry, entry_metadata=entry_metadata
for entry in entries: )
self._copy_entry_files_to_output_directory(entry=entry)
downloader.post_download(overrides=self.overrides) downloader.post_download(overrides=self.overrides)
for plugin in plugins:
plugin.post_process_subscription()
return self._enhanced_download_archive.get_file_handler_transaction_log() return self._enhanced_download_archive.get_file_handler_transaction_log()

View file

@ -11,7 +11,7 @@ from typing import Union
class FileMetadata: class FileMetadata:
""" """
Stores pretty-printed information about a file Stores pretty-printed information about a file. Each line in the metadata represents a newline
""" """
def __init__(self, metadata: Optional[List[str]] = None): def __init__(self, metadata: Optional[List[str]] = None):
@ -27,13 +27,14 @@ class FileMetadata:
self.metadata.append(line) self.metadata.append(line)
return self return self
def extend(self, other: "FileMetadata") -> "FileMetadata": def extend(self, other: Optional["FileMetadata"]) -> "FileMetadata":
""" """
Parameters Parameters
---------- ----------
other other
Other metadata to extend to this one in its entirety Other metadata to extend to this one in its entirety
""" """
if other is not None:
self.metadata.extend(other.metadata) self.metadata.extend(other.metadata)
return self return self
@ -146,7 +147,9 @@ class FileHandler:
if os.path.isfile(file_path): if os.path.isfile(file_path):
os.remove(file_path) os.remove(file_path)
def copy_file_to_output_directory(self, file_name: str, output_file_name: str): def copy_file_to_output_directory(
self, file_name: str, output_file_name: str, file_metadata: Optional[FileMetadata] = None
):
""" """
Copies a file from the working directory to the output directory. Copies a file from the working directory to the output directory.
All file copies from working to output directory should use this function for tracking and All file copies from working to output directory should use this function for tracking and
@ -158,8 +161,12 @@ class FileHandler:
File in the working directory File in the working directory
output_file_name output_file_name
Desired output file name in the output_directory Desired output file name in the output_directory
file_metadata
Optional. Metadata to record to the transaction log for this file
""" """
self._file_handler_transaction_log.log_created_file(output_file_name) self._file_handler_transaction_log.log_created_file(
file_name=output_file_name, file_metadata=file_metadata
)
if not self.dry_run: if not self.dry_run:
output_file_path = Path(self.output_directory) / output_file_name output_file_path = Path(self.output_directory) / output_file_name

View file

@ -15,6 +15,7 @@ from yt_dlp import DateRange
from ytdl_sub.entries.entry import Entry from ytdl_sub.entries.entry import Entry
from ytdl_sub.utils.file_handler import FileHandler from ytdl_sub.utils.file_handler import FileHandler
from ytdl_sub.utils.file_handler import FileHandlerTransactionLog from ytdl_sub.utils.file_handler import FileHandlerTransactionLog
from ytdl_sub.utils.file_handler import FileMetadata
from ytdl_sub.utils.logger import Logger from ytdl_sub.utils.logger import Logger
@ -547,15 +548,22 @@ class EnhancedDownloadArchive:
return self return self
def save_file_to_output_directory( def save_file_to_output_directory(
self, file_name: str, output_file_name: Optional[str] = None, entry: Optional[Entry] = None self,
file_name: str,
file_metadata: Optional[FileMetadata] = None,
output_file_name: Optional[str] = None,
entry: Optional[Entry] = None,
): ):
""" """
Saves a file from the working directory to the output directory Saves a file from the working directory to the output directory and record it in the
transaction log.
Parameters Parameters
---------- ----------
file_name file_name
Name of the file to move (does not include working directory path) Name of the file to move (does not include working directory path)
file_metadata
Optional. Metadata to record to the transaction log for this file
output_file_name output_file_name
Optional. Final name of the file in the output directory (does not include output Optional. Final name of the file in the output directory (does not include output
directory path). If None, use the same working_directory file_name directory path). If None, use the same working_directory file_name
@ -569,7 +577,7 @@ class EnhancedDownloadArchive:
self.mapping.add_entry(entry=entry, entry_file_path=output_file_name) self.mapping.add_entry(entry=entry, entry_file_path=output_file_name)
self._file_handler.copy_file_to_output_directory( self._file_handler.copy_file_to_output_directory(
file_name=file_name, output_file_name=output_file_name file_name=file_name, file_metadata=file_metadata, output_file_name=output_file_name
) )
def get_file_handler_transaction_log(self) -> FileHandlerTransactionLog: def get_file_handler_transaction_log(self) -> FileHandlerTransactionLog:
@ -609,7 +617,9 @@ class DownloadArchiver:
""" """
return self.__enhanced_download_archive.is_dry_run return self.__enhanced_download_archive.is_dry_run
def save_file(self, file_name: str, entry: Optional[Entry] = None) -> None: def save_file(
self, file_name: str, output_file_name: Optional[str] = None, entry: Optional[Entry] = None
) -> None:
""" """
Saves a file in the working directory to the output directory. Saves a file in the working directory to the output directory.
@ -617,9 +627,12 @@ class DownloadArchiver:
---------- ----------
file_name file_name
Name of the file relative to the working directory Name of the file relative to the working directory
output_file_name
Optional. Final name of the file in the output directory (does not include output
directory path). If None, use the same working_directory file_name
entry entry
Optional. Entry that the file belongs to Optional. Entry that the file belongs to
""" """
self.__enhanced_download_archive.save_file_to_output_directory( self.__enhanced_download_archive.save_file_to_output_directory(
file_name=file_name, entry=entry file_name=file_name, output_file_name=output_file_name, entry=entry
) )

View file

@ -81,8 +81,14 @@ class TestYoutubeMergePlaylist:
files exist and have the expected md5 file hashes. files exist and have the expected md5 file hashes.
""" """
def test_playlist_download( def test_merge_playlist_download(
self, playlist_subscription, expected_playlist_download, output_directory self, playlist_subscription, expected_playlist_download, output_directory
): ):
playlist_subscription.download() playlist_subscription.download()
expected_playlist_download.assert_files_exist(relative_directory=output_directory) expected_playlist_download.assert_files_exist(relative_directory=output_directory)
def test_merge_playlist_dry_run(
self, playlist_subscription, expected_playlist_download, output_directory
):
transaction_log = playlist_subscription.download(dry_run=True)
expected_playlist_download.assert_dry_run_files_logged(transaction_log=transaction_log)

View file

@ -119,8 +119,12 @@ class TestPlaylistAsKodiMusicVideo:
files exist and have the expected md5 file hashes. files exist and have the expected md5 file hashes.
""" """
def test_single_video_download( def test_split_video_download(
self, single_video_subscription, expected_single_video_download, output_directory self, single_video_subscription, expected_single_video_download, output_directory
): ):
single_video_subscription.download() single_video_subscription.download()
expected_single_video_download.assert_files_exist(relative_directory=output_directory) expected_single_video_download.assert_files_exist(relative_directory=output_directory)
def test_split_video_dry_run(self, single_video_subscription, expected_single_video_download):
transaction_log = single_video_subscription.download(dry_run=True)
expected_single_video_download.assert_dry_run_files_logged(transaction_log=transaction_log)