From e27a7c549537acebc3769d3d07dda76e2c615308 Mon Sep 17 00:00:00 2001 From: Jesse Bannon Date: Wed, 2 Apr 2025 21:22:12 -0700 Subject: [PATCH 1/4] [DOCKER] Fix various cron issues (#1204) Closes - https://github.com/jmbannon/ytdl-sub/issues/1200 - Runs in the background now - https://github.com/jmbannon/ytdl-sub/issues/1201 - Was not running as user `abc`, now it is - https://github.com/jmbannon/ytdl-sub/issues/1202 - Due to reading stdout and tail of hidden log file. Should only tail from hidden log file now Will leave crontab as-is if no CRON_SCHEDULE is specified --- docker/root/custom-cont-init.d/defaults | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/docker/root/custom-cont-init.d/defaults b/docker/root/custom-cont-init.d/defaults index e07ed6a8..cfbc0776 100644 --- a/docker/root/custom-cont-init.d/defaults +++ b/docker/root/custom-cont-init.d/defaults @@ -21,6 +21,9 @@ echo "Starting ytdl-sub..." chown -R ${PUID:-abc}:${PGID:-abc} \ /config +# always create empty cron log file on start +echo "" > "$LOGS_TO_STDOUT" + # set up cron if [ "$CRON_SCHEDULE" != "" ] ; then [[ ! -e "$CRON_SCRIPT" ]] && \ @@ -51,19 +54,15 @@ if [ "$CRON_SCHEDULE" != "" ] ; then echo "Cron enabled with schedule $CRON_SCHEDULE_CLEAN" if [ "$CRON_RUN_ON_START" = true ] ; then - echo "Running cron script on start" - . "$CRON_WRAPPER_SCRIPT" + echo "Running cron script on start in the background" + # ensure it runs as abc to respect puid/guid with delay for tail to start + su -s "/bin/bash" -c "sleep 5 && . '$CRON_WRAPPER_SCRIPT'" abc > /dev/null 2>&1 & fi else echo "Error in CRON_SCHEDULE definition, disabling cron." exit 1 fi else - echo "CRON_SCHEDULE not specified, disabling cron." - echo "# min hour day month weekday command" > /config/crontabs/abc - echo "" >> /config/crontabs/abc + echo "CRON_SCHEDULE not specified, leaving crontabs as-is. Current configuration in /config/crontabs/abc" + cat /config/crontabs/abc fi - -# always create cron log file, after cron runs -# on start to not tail it again -echo "" > "$LOGS_TO_STDOUT" From 19d28e9baa747585bdb273953b1e99c8be9188cb Mon Sep 17 00:00:00 2001 From: Jesse Bannon Date: Thu, 17 Apr 2025 22:14:37 -0700 Subject: [PATCH 2/4] [FEATURE] Throw more actionable error if users supply the wrong type of url for TV show presets (#1210) Don't let users supply `url` for TV Show Collection presets, or `s01_url` for TV Show by Date presets. --- .../tv_show/tv_show_by_date.yaml | 20 +++++++++++++- .../tv_show/tv_show_collection.yaml | 11 ++++++++ tests/unit/prebuilt_presets/__init__.py | 0 .../prebuilt_presets/test_tv_show_by_date.py | 26 +++++++++++++++++++ .../test_tv_show_collection.py | 26 +++++++++++++++++++ 5 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 tests/unit/prebuilt_presets/__init__.py create mode 100644 tests/unit/prebuilt_presets/test_tv_show_by_date.py create mode 100644 tests/unit/prebuilt_presets/test_tv_show_collection.py diff --git a/src/ytdl_sub/prebuilt_presets/tv_show/tv_show_by_date.yaml b/src/ytdl_sub/prebuilt_presets/tv_show/tv_show_by_date.yaml index e676ec82..bca76405 100644 --- a/src/ytdl_sub/prebuilt_presets/tv_show/tv_show_by_date.yaml +++ b/src/ytdl_sub/prebuilt_presets/tv_show/tv_show_by_date.yaml @@ -35,11 +35,29 @@ presets: # TV show from one or more sources. Uses {url}'s avatar and banner as poster and fanart _tv_show_by_date: - preset: "_multi_url_bilateral" + preset: + - "_multi_url_bilateral" + - "_tv_show_by_date_asserts" overrides: avatar_uncropped_thumbnail_file_name: "{tv_show_poster_file_name}" banner_uncropped_thumbnail_file_name: "{tv_show_fanart_file_name}" + _tv_show_by_date_asserts: + overrides: + s01_url: "" + s01_name: "" + assert_not_collection: >- + { + %assert( + %and( + %not( %bool(s01_url) ), + %not( %bool(s01_name) ) + ), + "Provided `s01_url` or `s01_name` variable to TV Show by Date preset when it expects `url`. Perhaps you meant to use the `TV Show Collection` preset?" + ) + } + + #################################################################################################### _season_by_year: diff --git a/src/ytdl_sub/prebuilt_presets/tv_show/tv_show_collection.yaml b/src/ytdl_sub/prebuilt_presets/tv_show/tv_show_collection.yaml index 888068d1..accdd395 100644 --- a/src/ytdl_sub/prebuilt_presets/tv_show/tv_show_collection.yaml +++ b/src/ytdl_sub/prebuilt_presets/tv_show/tv_show_collection.yaml @@ -62,6 +62,7 @@ presets: _tv_show_collection: preset: - "_tv_show_collection_bilateral" + - "_tv_show_collection_asserts" download: - url: "{collection_season_1_url}" @@ -1015,6 +1016,16 @@ presets: ytdl_options: playlist_items: "-1:0:-1" + _tv_show_collection_asserts: + overrides: + url: "" + assert_not_by_date: >- + { + %assert( + %not( %bool(url) ), + "Provided `url` to TV Show Collection preset when it expects `s01_url`. Perhaps you meant to use the `TV Show by Date` preset?" + ) + } #################################################################################################### # DEPRECATED SEASON PRESETS diff --git a/tests/unit/prebuilt_presets/__init__.py b/tests/unit/prebuilt_presets/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/unit/prebuilt_presets/test_tv_show_by_date.py b/tests/unit/prebuilt_presets/test_tv_show_by_date.py new file mode 100644 index 00000000..f8da99a7 --- /dev/null +++ b/tests/unit/prebuilt_presets/test_tv_show_by_date.py @@ -0,0 +1,26 @@ +import re + +import pytest + +from ytdl_sub.script.utils.exceptions import UserThrownRuntimeError +from ytdl_sub.subscriptions.subscription import Subscription + + +class TestTvShowByDatePreset: + + def test_s01_error_thrown(self, default_config): + with pytest.raises( + UserThrownRuntimeError, + match=re.escape( + "Provided `s01_url` or `s01_name` variable to TV Show by Date preset when it " + "expects `url`. Perhaps you meant to use the `TV Show Collection` preset?" + ), + ): + _ = Subscription.from_dict( + config=default_config, + preset_name="test", + preset_dict={ + "preset": "Jellyfin TV Show by Date", + "overrides": {"tv_show_directory": "abc", "s01_url": "test"}, + }, + ) diff --git a/tests/unit/prebuilt_presets/test_tv_show_collection.py b/tests/unit/prebuilt_presets/test_tv_show_collection.py new file mode 100644 index 00000000..3621f3cb --- /dev/null +++ b/tests/unit/prebuilt_presets/test_tv_show_collection.py @@ -0,0 +1,26 @@ +import re + +import pytest + +from ytdl_sub.script.utils.exceptions import UserThrownRuntimeError +from ytdl_sub.subscriptions.subscription import Subscription + + +class TestTvShowCollectionPreset: + + def test_url_error_thrown(self, default_config): + with pytest.raises( + UserThrownRuntimeError, + match=re.escape( + "Provided `url` to TV Show Collection preset when it expects `s01_url`. " + "Perhaps you meant to use the `TV Show by Date` preset?" + ), + ): + _ = Subscription.from_dict( + config=default_config, + preset_name="test", + preset_dict={ + "preset": "Jellyfin TV Show Collection", + "overrides": {"tv_show_directory": "abc", "url": "test"}, + }, + ) From a1681bf71adad1ef4b85299057e890f97e507da1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 May 2025 16:00:54 -0700 Subject: [PATCH 3/4] Bump yt-dlp[default] from 2025.3.31 to 2025.4.30 (#1213) Bumps [yt-dlp[default]](https://github.com/yt-dlp/yt-dlp) from 2025.3.31 to 2025.4.30. - [Release notes](https://github.com/yt-dlp/yt-dlp/releases) - [Changelog](https://github.com/yt-dlp/yt-dlp/blob/master/Changelog.md) - [Commits](https://github.com/yt-dlp/yt-dlp/compare/2025.03.31...2025.04.30) --- updated-dependencies: - dependency-name: yt-dlp[default] dependency-version: 2025.4.30 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 80d73970..91092da8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,7 +15,7 @@ classifiers = [ "Programming Language :: Python :: 3.11", ] dependencies = [ - "yt-dlp[default]==2025.3.31", + "yt-dlp[default]==2025.4.30", "colorama~=0.4", "mergedeep~=1.3", "mediafile~=0.12", From 0c0f05e4d0b1762a625747b0ff73fade68b677d3 Mon Sep 17 00:00:00 2001 From: Jesse Bannon Date: Sat, 3 May 2025 19:40:28 -0700 Subject: [PATCH 4/4] [DEV] Get windows testing in better state (#1214) --- Makefile | 6 +++--- tests/unit/validators/test_file_path_validators.py | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 39d8939d..6bdc1e1a 100644 --- a/Makefile +++ b/Makefile @@ -14,9 +14,9 @@ else endif lint: - @-isort . - @-black . - @-pylint src/ + python3 -m isort . && \ + python3 -m black . && \ + python3 -m pylint src check_lint: isort . --check-only --diff \ && black . --check \ diff --git a/tests/unit/validators/test_file_path_validators.py b/tests/unit/validators/test_file_path_validators.py index 467f7b80..e66a11c2 100644 --- a/tests/unit/validators/test_file_path_validators.py +++ b/tests/unit/validators/test_file_path_validators.py @@ -1,3 +1,4 @@ +import os import tempfile from pathlib import Path @@ -34,7 +35,8 @@ class TestStringFormatterFilePathValidator: Script({"file_name": formatter.format_string}).resolve().get_str("file_name") ) - assert truncated_file_path.count(".") == ext.count(".") + _, truncated_file_name = os.path.split(truncated_file_path) + assert truncated_file_name.count(".") == ext.count(".") assert str(Path(temp_dir)) in truncated_file_path assert ext in truncated_file_path