ytdl-sub 2025.11.8__tar.gz → 2025.12.31.post1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/PKG-INFO +2 -2
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/pyproject.toml +1 -1
- ytdl_sub-2025.12.31.post1/src/ytdl_sub/__init__.py +1 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/config/config_validator.py +8 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/config/overrides.py +44 -13
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/config/plugin/preset_plugins.py +33 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/config/preset.py +36 -8
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/config/preset_options.py +33 -2
- ytdl_sub-2025.12.31.post1/src/ytdl_sub/config/validators/variable_validation.py +91 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/downloaders/url/validators.py +2 -2
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/entries/variables/override_variables.py +1 -4
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/prebuilt_presets/helpers/download_deletion_options.yaml +1 -2
- ytdl_sub-2025.12.31.post1/src/ytdl_sub/prebuilt_presets/tv_show/tv_show_collection.yaml +5693 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/parser.py +6 -1
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/script.py +117 -46
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/types/function.py +11 -6
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/types/syntax_tree.py +28 -2
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/types/variable_dependency.py +16 -5
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/utils/name_validation.py +21 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/subscriptions/base_subscription.py +29 -3
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/subscriptions/subscription_download.py +3 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/utils/exceptions.py +4 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/utils/file_handler.py +49 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/utils/script.py +19 -2
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/validators/string_formatter_validators.py +63 -30
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/validators/validators.py +3 -13
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/ytdl_additions/enhanced_download_archive.py +20 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub.egg-info/PKG-INFO +2 -2
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub.egg-info/requires.txt +1 -1
- ytdl_sub-2025.11.8/src/ytdl_sub/__init__.py +0 -1
- ytdl_sub-2025.11.8/src/ytdl_sub/config/validators/variable_validation.py +0 -215
- ytdl_sub-2025.11.8/src/ytdl_sub/prebuilt_presets/tv_show/tv_show_collection.yaml +0 -1131
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/LICENSE +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/README.md +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/setup.cfg +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/cli/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/cli/entrypoint.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/cli/output_summary.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/cli/output_transaction_log.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/cli/parsers/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/cli/parsers/cli_to_sub.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/cli/parsers/dl.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/cli/parsers/main.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/config/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/config/config_file.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/config/defaults.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/config/plugin/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/config/plugin/plugin.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/config/plugin/plugin_mapping.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/config/plugin/plugin_operation.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/config/validators/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/config/validators/options.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/downloaders/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/downloaders/info_json/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/downloaders/info_json/info_json_downloader.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/downloaders/source_plugin.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/downloaders/url/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/downloaders/url/downloader.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/downloaders/ytdl_options_builder.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/downloaders/ytdlp.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/entries/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/entries/base_entry.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/entries/entry.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/entries/entry_parent.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/entries/script/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/entries/script/custom_functions.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/entries/script/function_scripts.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/entries/script/variable_definitions.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/entries/script/variable_types.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/entries/variables/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/main.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/plugins/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/plugins/audio_extract.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/plugins/chapters.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/plugins/date_range.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/plugins/embed_thumbnail.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/plugins/file_convert.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/plugins/filter_exclude.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/plugins/filter_include.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/plugins/format.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/plugins/internal/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/plugins/internal/view.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/plugins/match_filters.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/plugins/music_tags.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/plugins/nfo_tags.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/plugins/output_directory_nfo_tags.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/plugins/split_by_chapters.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/plugins/square_thumbnail.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/plugins/static_nfo_tags.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/plugins/subtitles.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/plugins/throttle_protection.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/plugins/video_tags.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/prebuilt_presets/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/prebuilt_presets/helpers/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/prebuilt_presets/helpers/filter_duration.yaml +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/prebuilt_presets/helpers/filter_keywords.yaml +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/prebuilt_presets/helpers/media_quality.yaml +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/prebuilt_presets/helpers/players.yaml +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/prebuilt_presets/helpers/throttle_protection.yaml +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/prebuilt_presets/helpers/url.yaml +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/prebuilt_presets/helpers/url_bilateral.yaml +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/prebuilt_presets/helpers/url_categorized.yaml +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/prebuilt_presets/internal/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/prebuilt_presets/internal/view.yaml +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/prebuilt_presets/music/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/prebuilt_presets/music/albums_from_chapters.yaml +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/prebuilt_presets/music/albums_from_playlists.yaml +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/prebuilt_presets/music/singles.yaml +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/prebuilt_presets/music/soundcloud.yaml +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/prebuilt_presets/music_videos/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/prebuilt_presets/music_videos/music_video_base.yaml +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/prebuilt_presets/music_videos/music_video_extras.yaml +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/prebuilt_presets/music_videos/music_videos.yaml +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/prebuilt_presets/tv_show/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/prebuilt_presets/tv_show/episode.yaml +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/prebuilt_presets/tv_show/tv_show.yaml +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/prebuilt_presets/tv_show/tv_show_by_date.yaml +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/functions/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/functions/array_functions.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/functions/boolean_functions.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/functions/conditional_functions.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/functions/date_functions.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/functions/error_functions.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/functions/json_functions.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/functions/map_functions.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/functions/numeric_functions.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/functions/print_functions.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/functions/regex_functions.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/functions/string_functions.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/script_output.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/types/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/types/array.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/types/map.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/types/resolvable.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/types/variable.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/utils/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/utils/exception_formatters.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/utils/exceptions.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/script/utils/type_checking.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/subscriptions/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/subscriptions/subscription.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/subscriptions/subscription_validators.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/subscriptions/subscription_ytdl_options.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/thread/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/thread/log_entries_downloaded_listener.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/utils/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/utils/chapters.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/utils/datetime.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/utils/ffmpeg.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/utils/file_lock.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/utils/file_path.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/utils/logger.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/utils/retry.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/utils/scriptable.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/utils/subtitles.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/utils/system.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/utils/thumbnail.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/utils/xml.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/utils/yaml.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/validators/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/validators/audo_codec_validator.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/validators/file_path_validators.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/validators/nfo_validators.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/validators/regex_validator.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/validators/source_variable_validator.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/validators/strict_dict_validator.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/validators/string_datetime.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/validators/string_select_validator.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/ytdl_additions/__init__.py +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub.egg-info/SOURCES.txt +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub.egg-info/dependency_links.txt +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub.egg-info/entry_points.txt +0 -0
- {ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ytdl-sub
|
|
3
|
-
Version: 2025.
|
|
3
|
+
Version: 2025.12.31.post1
|
|
4
4
|
Summary: Automate downloading metadata generation with YoutubeDL
|
|
5
5
|
Author: Jesse Bannon
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -689,7 +689,7 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
689
689
|
Requires-Python: >=3.10
|
|
690
690
|
Description-Content-Type: text/markdown
|
|
691
691
|
License-File: LICENSE
|
|
692
|
-
Requires-Dist: yt-dlp[default]==2025.
|
|
692
|
+
Requires-Dist: yt-dlp[default]==2025.12.8
|
|
693
693
|
Requires-Dist: colorama~=0.4
|
|
694
694
|
Requires-Dist: mergedeep~=1.3
|
|
695
695
|
Requires-Dist: mediafile~=0.12
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__pypi_version__ = "2025.12.31.post1";__local_version__ = "2025.12.31+d373935"
|
|
@@ -12,6 +12,8 @@ from ytdl_sub.config.defaults import DEFAULT_FFPROBE_PATH
|
|
|
12
12
|
from ytdl_sub.config.defaults import DEFAULT_LOCK_DIRECTORY
|
|
13
13
|
from ytdl_sub.config.defaults import MAX_FILE_NAME_BYTES
|
|
14
14
|
from ytdl_sub.prebuilt_presets import PREBUILT_PRESETS
|
|
15
|
+
from ytdl_sub.utils.exceptions import SubscriptionPermissionError
|
|
16
|
+
from ytdl_sub.utils.file_handler import FileHandler
|
|
15
17
|
from ytdl_sub.validators.file_path_validators import FFmpegFileValidator
|
|
16
18
|
from ytdl_sub.validators.file_path_validators import FFprobeFileValidator
|
|
17
19
|
from ytdl_sub.validators.strict_dict_validator import StrictDictValidator
|
|
@@ -147,6 +149,12 @@ class ConfigOptions(StrictDictValidator):
|
|
|
147
149
|
key="file_name_max_bytes", validator=IntValidator, default=MAX_FILE_NAME_BYTES
|
|
148
150
|
)
|
|
149
151
|
|
|
152
|
+
if not FileHandler.is_path_writable(self.working_directory):
|
|
153
|
+
raise SubscriptionPermissionError(
|
|
154
|
+
"ytdl-sub does not have permissions to the working directory: "
|
|
155
|
+
f"{self.working_directory}"
|
|
156
|
+
)
|
|
157
|
+
|
|
150
158
|
@property
|
|
151
159
|
def working_directory(self) -> str:
|
|
152
160
|
"""
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
from typing import Any
|
|
2
2
|
from typing import Dict
|
|
3
|
+
from typing import Iterable
|
|
3
4
|
from typing import Optional
|
|
4
5
|
from typing import Set
|
|
5
6
|
|
|
6
|
-
import mergedeep
|
|
7
|
-
|
|
8
7
|
from ytdl_sub.entries.entry import Entry
|
|
9
8
|
from ytdl_sub.entries.script.variable_definitions import VARIABLES
|
|
10
9
|
from ytdl_sub.entries.variables.override_variables import REQUIRED_OVERRIDE_VARIABLE_NAMES
|
|
11
10
|
from ytdl_sub.entries.variables.override_variables import OverrideHelpers
|
|
12
11
|
from ytdl_sub.script.parser import parse
|
|
13
12
|
from ytdl_sub.script.script import Script
|
|
13
|
+
from ytdl_sub.script.types.function import BuiltInFunction
|
|
14
14
|
from ytdl_sub.script.types.resolvable import Resolvable
|
|
15
|
+
from ytdl_sub.script.types.resolvable import String
|
|
16
|
+
from ytdl_sub.script.types.syntax_tree import SyntaxTree
|
|
15
17
|
from ytdl_sub.script.utils.exceptions import ScriptVariableNotResolved
|
|
16
18
|
from ytdl_sub.utils.exceptions import InvalidVariableNameException
|
|
17
19
|
from ytdl_sub.utils.exceptions import StringFormattingException
|
|
@@ -88,6 +90,24 @@ class Overrides(UnstructuredDictFormatterValidator, Scriptable):
|
|
|
88
90
|
|
|
89
91
|
return True
|
|
90
92
|
|
|
93
|
+
def ensure_variable_names_not_a_plugin(self, plugin_names: Iterable[str]) -> None:
|
|
94
|
+
"""
|
|
95
|
+
Throws an error if an override variable or function has the same name as a
|
|
96
|
+
preset key. This is to avoid confusion when accidentally defining things in
|
|
97
|
+
overrides that are meant to be in the preset.
|
|
98
|
+
"""
|
|
99
|
+
for name in self.keys:
|
|
100
|
+
if name.startswith("%"):
|
|
101
|
+
name = name[1:]
|
|
102
|
+
|
|
103
|
+
if name in plugin_names:
|
|
104
|
+
raise self._validation_exception(
|
|
105
|
+
f"Override variable with name {name} cannot be used since it is"
|
|
106
|
+
" the name of a plugin. Perhaps you meant to define it as a plugin? If so,"
|
|
107
|
+
" indent it left to make it at the same level as overrides.",
|
|
108
|
+
exception_class=InvalidVariableNameException,
|
|
109
|
+
)
|
|
110
|
+
|
|
91
111
|
def ensure_variable_name_valid(self, name: str) -> None:
|
|
92
112
|
"""
|
|
93
113
|
Ensures the variable name does not collide with any entry variables or built-in functions.
|
|
@@ -115,29 +135,35 @@ class Overrides(UnstructuredDictFormatterValidator, Scriptable):
|
|
|
115
135
|
)
|
|
116
136
|
|
|
117
137
|
def initial_variables(
|
|
118
|
-
self, unresolved_variables: Optional[Dict[str,
|
|
119
|
-
) -> Dict[str,
|
|
138
|
+
self, unresolved_variables: Optional[Dict[str, SyntaxTree]] = None
|
|
139
|
+
) -> Dict[str, SyntaxTree]:
|
|
120
140
|
"""
|
|
121
141
|
Returns
|
|
122
142
|
-------
|
|
123
143
|
Variables and format strings for all Override variables + additional variables (Optional)
|
|
124
144
|
"""
|
|
125
|
-
initial_variables: Dict[str,
|
|
126
|
-
|
|
127
|
-
initial_variables
|
|
128
|
-
|
|
129
|
-
unresolved_variables if unresolved_variables else {},
|
|
130
|
-
)
|
|
131
|
-
return ScriptUtils.add_sanitized_variables(initial_variables)
|
|
145
|
+
initial_variables: Dict[str, SyntaxTree] = self.dict_with_parsed_format_strings
|
|
146
|
+
if unresolved_variables:
|
|
147
|
+
initial_variables |= unresolved_variables
|
|
148
|
+
return ScriptUtils.add_sanitized_parsed_variables(initial_variables)
|
|
132
149
|
|
|
133
150
|
def initialize_script(self, unresolved_variables: Set[str]) -> "Overrides":
|
|
134
151
|
"""
|
|
135
152
|
Initialize the override script with any unresolved variables
|
|
136
153
|
"""
|
|
137
|
-
self.script.
|
|
154
|
+
self.script.add_parsed(
|
|
138
155
|
self.initial_variables(
|
|
139
156
|
unresolved_variables={
|
|
140
|
-
var_name:
|
|
157
|
+
var_name: SyntaxTree(
|
|
158
|
+
ast=[
|
|
159
|
+
BuiltInFunction(
|
|
160
|
+
name="throw",
|
|
161
|
+
args=[
|
|
162
|
+
String(f"Plugin variable {var_name} has not been created yet")
|
|
163
|
+
],
|
|
164
|
+
)
|
|
165
|
+
]
|
|
166
|
+
)
|
|
141
167
|
for var_name in unresolved_variables
|
|
142
168
|
}
|
|
143
169
|
)
|
|
@@ -158,10 +184,15 @@ class Overrides(UnstructuredDictFormatterValidator, Scriptable):
|
|
|
158
184
|
script = entry.script
|
|
159
185
|
unresolvable = entry.unresolvable
|
|
160
186
|
|
|
187
|
+
# Update the script internally so long as we are not supplying overrides
|
|
188
|
+
# that could alter the script with one-off state
|
|
189
|
+
update = function_overrides is None
|
|
190
|
+
|
|
161
191
|
try:
|
|
162
192
|
return script.resolve_once(
|
|
163
193
|
dict({"tmp_var": formatter.format_string}, **(function_overrides or {})),
|
|
164
194
|
unresolvable=unresolvable,
|
|
195
|
+
update=update,
|
|
165
196
|
)["tmp_var"]
|
|
166
197
|
except ScriptVariableNotResolved as exc:
|
|
167
198
|
raise StringFormattingException(
|
{ytdl_sub-2025.11.8 → ytdl_sub-2025.12.31.post1}/src/ytdl_sub/config/plugin/preset_plugins.py
RENAMED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
from typing import Iterable
|
|
1
2
|
from typing import List
|
|
2
3
|
from typing import Optional
|
|
4
|
+
from typing import Set
|
|
3
5
|
from typing import Tuple
|
|
4
6
|
from typing import Type
|
|
5
7
|
|
|
@@ -44,3 +46,34 @@ class PresetPlugins:
|
|
|
44
46
|
if plugin_type in plugin_option_types:
|
|
45
47
|
return self.plugin_options[plugin_option_types.index(plugin_type)]
|
|
46
48
|
return None
|
|
49
|
+
|
|
50
|
+
def get_added_and_modified_variables(
|
|
51
|
+
self, additional_options: List[OptionsValidator]
|
|
52
|
+
) -> Iterable[Tuple[OptionsValidator, Set[str], Set[str]]]:
|
|
53
|
+
"""
|
|
54
|
+
Iterates and returns the plugin options, added variables, modified variables
|
|
55
|
+
"""
|
|
56
|
+
for plugin_options in self.plugin_options + additional_options:
|
|
57
|
+
added_variables: Set[str] = set()
|
|
58
|
+
modified_variables: Set[str] = set()
|
|
59
|
+
|
|
60
|
+
for plugin_added_variables in plugin_options.added_variables(
|
|
61
|
+
unresolved_variables=set(),
|
|
62
|
+
).values():
|
|
63
|
+
added_variables |= set(plugin_added_variables)
|
|
64
|
+
|
|
65
|
+
for plugin_modified_variables in plugin_options.modified_variables().values():
|
|
66
|
+
modified_variables = plugin_modified_variables
|
|
67
|
+
|
|
68
|
+
yield plugin_options, added_variables, modified_variables
|
|
69
|
+
|
|
70
|
+
def get_all_variables(self, additional_options: List[OptionsValidator]) -> Set[str]:
|
|
71
|
+
"""
|
|
72
|
+
Returns set of all added and modified variables' names.
|
|
73
|
+
"""
|
|
74
|
+
all_variables: Set[str] = set()
|
|
75
|
+
for _, added, modified in self.get_added_and_modified_variables(additional_options):
|
|
76
|
+
all_variables.update(added)
|
|
77
|
+
all_variables.update(modified)
|
|
78
|
+
|
|
79
|
+
return all_variables
|
|
@@ -2,6 +2,7 @@ import copy
|
|
|
2
2
|
from typing import Any
|
|
3
3
|
from typing import Dict
|
|
4
4
|
from typing import List
|
|
5
|
+
from typing import Set
|
|
5
6
|
|
|
6
7
|
from mergedeep import mergedeep
|
|
7
8
|
|
|
@@ -11,7 +12,6 @@ from ytdl_sub.config.plugin.plugin_mapping import PluginMapping
|
|
|
11
12
|
from ytdl_sub.config.plugin.preset_plugins import PresetPlugins
|
|
12
13
|
from ytdl_sub.config.preset_options import OutputOptions
|
|
13
14
|
from ytdl_sub.config.preset_options import YTDLOptions
|
|
14
|
-
from ytdl_sub.config.validators.variable_validation import VariableValidation
|
|
15
15
|
from ytdl_sub.downloaders.url.validators import MultiUrlValidator
|
|
16
16
|
from ytdl_sub.prebuilt_presets import PREBUILT_PRESET_NAMES
|
|
17
17
|
from ytdl_sub.prebuilt_presets import PUBLISHED_PRESET_NAMES
|
|
@@ -172,6 +172,37 @@ class Preset(_PresetShell):
|
|
|
172
172
|
mergedeep.merge({}, *reversed(presets_to_merge), strategy=mergedeep.Strategy.ADDITIVE)
|
|
173
173
|
)
|
|
174
174
|
|
|
175
|
+
def _initialize_overrides_script(self, overrides: Overrides) -> Overrides:
|
|
176
|
+
"""
|
|
177
|
+
Do some gymnastics to initialize the Overrides script.
|
|
178
|
+
"""
|
|
179
|
+
unresolved_variables: Set[str] = set()
|
|
180
|
+
|
|
181
|
+
for (
|
|
182
|
+
plugin_options,
|
|
183
|
+
added_variables,
|
|
184
|
+
modified_variables,
|
|
185
|
+
) in self.plugins.get_added_and_modified_variables(
|
|
186
|
+
additional_options=[self.downloader_options, self.output_options]
|
|
187
|
+
):
|
|
188
|
+
for added_variable in added_variables:
|
|
189
|
+
if not overrides.ensure_added_plugin_variable_valid(added_variable=added_variable):
|
|
190
|
+
# pylint: disable=protected-access
|
|
191
|
+
raise plugin_options._validation_exception(
|
|
192
|
+
f"Cannot use the variable name {added_variable} because it exists as a"
|
|
193
|
+
" built-in ytdl-sub variable name."
|
|
194
|
+
)
|
|
195
|
+
# pylint: enable=protected-access
|
|
196
|
+
|
|
197
|
+
# Set unresolved as variables that are added but do not exist as
|
|
198
|
+
# entry/override variables since they are created at run-time
|
|
199
|
+
unresolved_variables |= added_variables | modified_variables
|
|
200
|
+
|
|
201
|
+
# Initialize overrides with unresolved variables + modified variables to throw an error.
|
|
202
|
+
# For modified variables, this is to prevent a resolve(update=True) to setting any
|
|
203
|
+
# dependencies until it has been explicitly added
|
|
204
|
+
return overrides.initialize_script(unresolved_variables=unresolved_variables)
|
|
205
|
+
|
|
175
206
|
def __init__(self, config: ConfigValidator, name: str, value: Any):
|
|
176
207
|
super().__init__(name=name, value=value)
|
|
177
208
|
|
|
@@ -192,13 +223,10 @@ class Preset(_PresetShell):
|
|
|
192
223
|
)
|
|
193
224
|
|
|
194
225
|
self.plugins: PresetPlugins = self._validate_and_get_plugins()
|
|
195
|
-
self.overrides = self.
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
output_options=self.output_options,
|
|
200
|
-
plugins=self.plugins,
|
|
201
|
-
).initialize_preset_overrides(overrides=self.overrides).ensure_proper_usage()
|
|
226
|
+
self.overrides = self._initialize_overrides_script(
|
|
227
|
+
overrides=self._validate_key(key="overrides", validator=Overrides, default={})
|
|
228
|
+
)
|
|
229
|
+
self.overrides.ensure_variable_names_not_a_plugin(plugin_names=PRESET_KEYS)
|
|
202
230
|
|
|
203
231
|
@property
|
|
204
232
|
def name(self) -> str:
|
|
@@ -8,6 +8,9 @@ from ytdl_sub.config.overrides import Overrides
|
|
|
8
8
|
from ytdl_sub.config.plugin.plugin_operation import PluginOperation
|
|
9
9
|
from ytdl_sub.config.validators.options import OptionsDictValidator
|
|
10
10
|
from ytdl_sub.entries.script.variable_definitions import VARIABLES as v
|
|
11
|
+
from ytdl_sub.utils.exceptions import SubscriptionPermissionError
|
|
12
|
+
from ytdl_sub.utils.exceptions import ValidationException
|
|
13
|
+
from ytdl_sub.utils.file_handler import FileHandler
|
|
11
14
|
from ytdl_sub.validators.file_path_validators import OverridesStringFormatterFilePathValidator
|
|
12
15
|
from ytdl_sub.validators.file_path_validators import StringFormatterFileNameValidator
|
|
13
16
|
from ytdl_sub.validators.string_datetime import StringDatetimeValidator
|
|
@@ -57,12 +60,24 @@ class YTDLOptions(UnstructuredOverridesDictFormatterValidator):
|
|
|
57
60
|
def to_native_dict(self, overrides: Overrides) -> Dict:
|
|
58
61
|
"""
|
|
59
62
|
Materializes the entire ytdl-options dict from OverrideStringFormatters into
|
|
60
|
-
native python
|
|
63
|
+
native python.
|
|
61
64
|
"""
|
|
62
|
-
|
|
65
|
+
out = {
|
|
63
66
|
key: overrides.apply_overrides_formatter_to_native(val)
|
|
64
67
|
for key, val in self.dict.items()
|
|
65
68
|
}
|
|
69
|
+
if "cookiefile" in out:
|
|
70
|
+
if not FileHandler.is_file_existent(out["cookiefile"]):
|
|
71
|
+
raise ValidationException(
|
|
72
|
+
f"Specified cookiefile {out['cookiefile']} but it does not exist as a file."
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
if not FileHandler.is_file_readable(out["cookiefile"]):
|
|
76
|
+
raise SubscriptionPermissionError(
|
|
77
|
+
f"Cannot read cookiefile {out['cookiefile']} due to permissions issue."
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
return out
|
|
66
81
|
|
|
67
82
|
|
|
68
83
|
# Disable for proper docstring formatting
|
|
@@ -107,6 +122,7 @@ class OutputOptions(OptionsDictValidator):
|
|
|
107
122
|
"keep_max_files",
|
|
108
123
|
"download_archive_standardized_date",
|
|
109
124
|
"keep_files_date_eval",
|
|
125
|
+
"preserve_mtime",
|
|
110
126
|
}
|
|
111
127
|
|
|
112
128
|
@classmethod
|
|
@@ -170,6 +186,10 @@ class OutputOptions(OptionsDictValidator):
|
|
|
170
186
|
default=f"{{{v.upload_date_standardized.variable_name}}}",
|
|
171
187
|
)
|
|
172
188
|
|
|
189
|
+
self._preserve_mtime = self._validate_key_if_present(
|
|
190
|
+
key="preserve_mtime", validator=BoolValidator, default=False
|
|
191
|
+
)
|
|
192
|
+
|
|
173
193
|
if (
|
|
174
194
|
self._keep_files_before or self._keep_files_after or self._keep_max_files
|
|
175
195
|
) and not self.maintain_download_archive:
|
|
@@ -309,6 +329,17 @@ class OutputOptions(OptionsDictValidator):
|
|
|
309
329
|
"""
|
|
310
330
|
return self._keep_max_files
|
|
311
331
|
|
|
332
|
+
@property
|
|
333
|
+
def preserve_mtime(self) -> bool:
|
|
334
|
+
"""
|
|
335
|
+
:expected type: Optional[Boolean]
|
|
336
|
+
:description:
|
|
337
|
+
Preserve the video's original upload time as the file modification time.
|
|
338
|
+
When True, sets the file's mtime to match the video's upload_date from
|
|
339
|
+
yt-dlp metadata. Defaults to False.
|
|
340
|
+
"""
|
|
341
|
+
return self._preserve_mtime.value
|
|
342
|
+
|
|
312
343
|
def added_variables(self, unresolved_variables: Set[str]) -> Dict[PluginOperation, Set[str]]:
|
|
313
344
|
return {
|
|
314
345
|
# PluginOperation.MODIFY_ENTRY_METADATA: {
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
from typing import Dict
|
|
2
|
+
|
|
3
|
+
from ytdl_sub.config.overrides import Overrides
|
|
4
|
+
from ytdl_sub.config.plugin.plugin_mapping import PluginMapping
|
|
5
|
+
from ytdl_sub.config.plugin.plugin_operation import PluginOperation
|
|
6
|
+
from ytdl_sub.config.plugin.preset_plugins import PresetPlugins
|
|
7
|
+
from ytdl_sub.config.preset_options import OutputOptions
|
|
8
|
+
from ytdl_sub.config.validators.options import OptionsValidator
|
|
9
|
+
from ytdl_sub.downloaders.url.validators import MultiUrlValidator
|
|
10
|
+
from ytdl_sub.validators.string_formatter_validators import validate_formatters
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class VariableValidation:
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
overrides: Overrides,
|
|
17
|
+
downloader_options: MultiUrlValidator,
|
|
18
|
+
output_options: OutputOptions,
|
|
19
|
+
plugins: PresetPlugins,
|
|
20
|
+
):
|
|
21
|
+
self.overrides = overrides
|
|
22
|
+
self.downloader_options = downloader_options
|
|
23
|
+
self.output_options = output_options
|
|
24
|
+
self.plugins = plugins
|
|
25
|
+
|
|
26
|
+
self.script = self.overrides.script
|
|
27
|
+
self.unresolved_variables = self.plugins.get_all_variables(
|
|
28
|
+
additional_options=[self.output_options, self.downloader_options]
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
def _add_variables(self, plugin_op: PluginOperation, options: OptionsValidator) -> None:
|
|
32
|
+
"""
|
|
33
|
+
Add dummy variables for script validation
|
|
34
|
+
"""
|
|
35
|
+
added_variables = options.added_variables(
|
|
36
|
+
unresolved_variables=self.unresolved_variables,
|
|
37
|
+
).get(plugin_op, set())
|
|
38
|
+
modified_variables = options.modified_variables().get(plugin_op, set())
|
|
39
|
+
|
|
40
|
+
self.unresolved_variables -= added_variables | modified_variables
|
|
41
|
+
|
|
42
|
+
def ensure_proper_usage(self) -> Dict:
|
|
43
|
+
"""
|
|
44
|
+
Validate variables resolve as plugins are executed, and return
|
|
45
|
+
a mock script which contains actualized added variables from the plugins
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
resolved_subscription: Dict = {}
|
|
49
|
+
|
|
50
|
+
self._add_variables(PluginOperation.DOWNLOADER, options=self.downloader_options)
|
|
51
|
+
|
|
52
|
+
# Always add output options first
|
|
53
|
+
self._add_variables(PluginOperation.MODIFY_ENTRY_METADATA, options=self.output_options)
|
|
54
|
+
|
|
55
|
+
# Metadata variables to be added
|
|
56
|
+
for plugin_options in PluginMapping.order_options_by(
|
|
57
|
+
self.plugins.zipped(), PluginOperation.MODIFY_ENTRY_METADATA
|
|
58
|
+
):
|
|
59
|
+
self._add_variables(PluginOperation.MODIFY_ENTRY_METADATA, options=plugin_options)
|
|
60
|
+
|
|
61
|
+
for plugin_options in PluginMapping.order_options_by(
|
|
62
|
+
self.plugins.zipped(), PluginOperation.MODIFY_ENTRY
|
|
63
|
+
):
|
|
64
|
+
self._add_variables(PluginOperation.MODIFY_ENTRY, options=plugin_options)
|
|
65
|
+
|
|
66
|
+
# Validate that any formatter in the plugin options can resolve
|
|
67
|
+
resolved_subscription |= validate_formatters(
|
|
68
|
+
script=self.script,
|
|
69
|
+
unresolved_variables=self.unresolved_variables,
|
|
70
|
+
validator=plugin_options,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
resolved_subscription |= validate_formatters(
|
|
74
|
+
script=self.script,
|
|
75
|
+
unresolved_variables=self.unresolved_variables,
|
|
76
|
+
validator=self.output_options,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# TODO: make this a function
|
|
80
|
+
raw_download_output = validate_formatters(
|
|
81
|
+
script=self.script,
|
|
82
|
+
unresolved_variables=self.unresolved_variables,
|
|
83
|
+
validator=self.downloader_options.urls,
|
|
84
|
+
)
|
|
85
|
+
resolved_subscription["download"] = []
|
|
86
|
+
for url_output in raw_download_output["download"]:
|
|
87
|
+
if url_output["url"]:
|
|
88
|
+
resolved_subscription["download"].append(url_output)
|
|
89
|
+
|
|
90
|
+
assert not self.unresolved_variables
|
|
91
|
+
return resolved_subscription
|
|
@@ -21,7 +21,7 @@ class UrlThumbnailValidator(StrictDictValidator):
|
|
|
21
21
|
def __init__(self, name, value):
|
|
22
22
|
super().__init__(name, value)
|
|
23
23
|
|
|
24
|
-
self.
|
|
24
|
+
self._thumb_name = self._validate_key(key="name", validator=StringFormatterValidator)
|
|
25
25
|
self._uid = self._validate_key(key="uid", validator=OverridesStringFormatterValidator)
|
|
26
26
|
|
|
27
27
|
@property
|
|
@@ -29,7 +29,7 @@ class UrlThumbnailValidator(StrictDictValidator):
|
|
|
29
29
|
"""
|
|
30
30
|
File name for the thumbnail
|
|
31
31
|
"""
|
|
32
|
-
return self.
|
|
32
|
+
return self._thumb_name
|
|
33
33
|
|
|
34
34
|
@property
|
|
35
35
|
def uid(self) -> OverridesStringFormatterValidator:
|
|
@@ -11,9 +11,6 @@ from ytdl_sub.entries.script.variable_types import Variable
|
|
|
11
11
|
from ytdl_sub.script.functions import Functions
|
|
12
12
|
from ytdl_sub.script.utils.name_validation import is_valid_name
|
|
13
13
|
|
|
14
|
-
# TODO: use this
|
|
15
|
-
SUBSCRIPTION_ARRAY = "subscription_array"
|
|
16
|
-
|
|
17
14
|
|
|
18
15
|
class SubscriptionVariables:
|
|
19
16
|
@staticmethod
|
|
@@ -163,7 +160,7 @@ class OverrideHelpers:
|
|
|
163
160
|
True if the override name itself is valid. False otherwise.
|
|
164
161
|
"""
|
|
165
162
|
if name.startswith("%"):
|
|
166
|
-
|
|
163
|
+
name = name[1:]
|
|
167
164
|
|
|
168
165
|
return is_valid_name(name=name)
|
|
169
166
|
|
|
@@ -11,8 +11,7 @@ presets:
|
|
|
11
11
|
|
|
12
12
|
# Set the default date_range to 2 months
|
|
13
13
|
overrides:
|
|
14
|
-
|
|
15
|
-
only_recent_date_range: "{date_range}"
|
|
14
|
+
only_recent_date_range: "2months"
|
|
16
15
|
|
|
17
16
|
#############################################################################
|
|
18
17
|
# Only Recent
|