refactor CLI command modules and synchronize docs

This commit is contained in:
windyboy
2026-02-16 12:31:26 +08:00
parent 0be802eac5
commit 2dd329cba9
41 changed files with 1066 additions and 753 deletions
+46 -46
View File
@@ -1,7 +1,7 @@
"""Unit tests for plan generator."""
import pytest
from datetime import datetime
from datetime import datetime, timezone
from pathlib import Path
from vlm.config import Config
@@ -36,7 +36,7 @@ def test_generate_plan_for_movie_with_year(config):
path=Path("/mnt/nas/videos/movie/Some.Movie.2020.1080p.mkv"),
filename="Some.Movie.2020.1080p.mkv",
size_bytes=1000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie"
)
@@ -67,7 +67,7 @@ def test_generate_plan_for_movie_without_year(config):
path=Path("/mnt/nas/videos/movie/random_movie.mkv"),
filename="random_movie.mkv",
size_bytes=1000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie"
)
@@ -94,7 +94,7 @@ def test_generate_plan_for_series_with_season_and_episode(config):
path=Path("/mnt/nas/videos/series/Show.Name.S01E05.mkv"),
filename="Show.Name.S01E05.mkv",
size_bytes=500000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="series"
)
@@ -123,7 +123,7 @@ def test_generate_plan_blocks_series_with_high_season(config):
path=Path("/mnt/nas/videos/series/Show.Name.S20E01.mkv"),
filename="Show.Name.S20E01.mkv",
size_bytes=500000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="series"
)
identity = SeriesIdentity(
@@ -147,7 +147,7 @@ def test_generate_plan_blocks_series_with_high_episode(config):
path=Path("/mnt/nas/videos/series/Show.Name.S01E120.mkv"),
filename="Show.Name.S01E120.mkv",
size_bytes=500000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="series"
)
identity = SeriesIdentity(
@@ -171,7 +171,7 @@ def test_generate_plan_sample_is_noop_by_default(config):
path=Path("/mnt/nas/videos/series/Show.Name.Sample.S01E01.mkv"),
filename="Show.Name.Sample.S01E01.mkv",
size_bytes=500000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="series"
)
identity = SeriesIdentity(
@@ -196,7 +196,7 @@ def test_generate_plan_sample_can_be_included_via_config(config):
path=Path("/mnt/nas/videos/series/Show.Name.Sample.S01E01.mkv"),
filename="Show.Name.Sample.S01E01.mkv",
size_bytes=500000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="series"
)
identity = SeriesIdentity(
@@ -219,7 +219,7 @@ def test_generate_plan_for_series_without_season(config):
path=Path("/mnt/nas/videos/series/ambiguous_show.mkv"),
filename="ambiguous_show.mkv",
size_bytes=500000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="series"
)
@@ -247,7 +247,7 @@ def test_generate_plan_for_anime_category(config):
path=Path("/mnt/nas/videos/anime/Some.Anime.01.mkv"),
filename="Some.Anime.01.mkv",
size_bytes=500000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="anime"
)
@@ -267,7 +267,7 @@ def test_generate_plan_for_other_category(config):
path=Path("/mnt/nas/videos/other/random.mkv"),
filename="random.mkv",
size_bytes=500000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="other"
)
@@ -286,7 +286,7 @@ def test_generate_plan_preserves_category_boundaries(config):
path=Path("/mnt/nas/videos/movie/Movie.2020.mkv"),
filename="Movie.2020.mkv",
size_bytes=1000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie"
)
@@ -311,7 +311,7 @@ def test_generate_plan_for_multi_episode_file(config):
path=Path("/mnt/nas/videos/series/Show.S01E01E02.mkv"),
filename="Show.S01E01E02.mkv",
size_bytes=1000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="series"
)
@@ -338,7 +338,7 @@ def test_generate_plan_file_already_at_target(config):
path=Path("/mnt/nas/videos/movie/Some Movie (2020)/Some Movie (2020).mkv"),
filename="Some Movie (2020).mkv",
size_bytes=1000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie"
)
@@ -364,7 +364,7 @@ def test_generate_plan_rename_vs_move(config):
path=Path("/mnt/nas/videos/movie/Some Movie (2020)/old_name.mkv"),
filename="old_name.mkv",
size_bytes=1000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie"
)
@@ -385,7 +385,7 @@ def test_generate_plan_rename_vs_move(config):
path=Path("/mnt/nas/videos/movie/wrong_dir/Some Movie (2020).mkv"),
filename="Some Movie (2020).mkv",
size_bytes=1000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie"
)
@@ -403,7 +403,7 @@ def test_generate_plan_summary(config):
path=Path("/mnt/nas/videos/movie/Movie1.2020.mkv"),
filename="Movie1.2020.mkv",
size_bytes=1000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie"
),
MovieIdentity(
@@ -420,7 +420,7 @@ def test_generate_plan_summary(config):
path=Path("/mnt/nas/videos/movie/Movie2.mkv"),
filename="Movie2.mkv",
size_bytes=1000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie"
),
MovieIdentity(
@@ -437,7 +437,7 @@ def test_generate_plan_summary(config):
path=Path("/mnt/nas/videos/anime/Anime.01.mkv"),
filename="Anime.01.mkv",
size_bytes=500000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="anime"
),
None
@@ -448,7 +448,7 @@ def test_generate_plan_summary(config):
path=Path("/mnt/nas/videos/series/Show.S01E01.mkv"),
filename="Show.S01E01.mkv",
size_bytes=500000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="series"
),
SeriesIdentity(
@@ -480,14 +480,14 @@ def test_generate_plan_with_analysis_by_quality(config):
path=p_720,
filename="Test.2020.720p.WEB-DL.mkv",
size_bytes=1000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie",
)
vf_1080 = VideoFile(
path=p_1080,
filename="Test.2020.1080p.BluRay.mkv",
size_bytes=2000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie",
)
identity = MovieIdentity(
@@ -528,14 +528,14 @@ def test_generate_plan_with_analysis_by_reputation_quality_time_reason(config):
path=p_old,
filename="Test.2020.720p.WEB-DL.mkv",
size_bytes=1000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie",
)
vf_new = VideoFile(
path=p_new,
filename="Test.2020.1080p.BluRay.mkv",
size_bytes=2000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie",
)
identity = MovieIdentity(
@@ -574,14 +574,14 @@ def test_generate_plan_with_analysis_by_reputation_missing_scores_uses_fallback_
path=p_web,
filename="Test.2020.2160p.WEB-DL.mkv",
size_bytes=3000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie",
)
vf_bluray = VideoFile(
path=p_bluray,
filename="Test.2020.1080p.BluRay.mkv",
size_bytes=2000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie",
)
identity = MovieIdentity(
@@ -622,14 +622,14 @@ def test_generate_plan_human_summary_marks_disc_files_as_high_risk(config):
path=p_disc1,
filename="The.Best.of.Youth.DISC1.mkv",
size_bytes=2000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie",
)
vf2 = VideoFile(
path=p_disc2,
filename="The.Best.of.Youth.DISC2.mkv",
size_bytes=1800000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie",
)
identity = MovieIdentity(
@@ -669,7 +669,7 @@ def test_generate_plan_with_different_extensions(config):
path=Path(f"/mnt/nas/videos/movie/Movie.2020{ext}"),
filename=f"Movie.2020{ext}",
size_bytes=1000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie"
)
@@ -704,7 +704,7 @@ def test_conflict_detection_for_movie(config, tmp_path):
path=tmp_path / "movie" / "Some.Movie.2020.1080p.mkv",
filename="Some.Movie.2020.1080p.mkv",
size_bytes=1000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie"
)
@@ -741,7 +741,7 @@ def test_conflict_detection_for_series(config, tmp_path):
path=tmp_path / "series" / "Show.Name.S01E05.1080p.mkv",
filename="Show.Name.S01E05.1080p.mkv",
size_bytes=500000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="series"
)
@@ -776,7 +776,7 @@ def test_no_conflict_when_destination_does_not_exist(config, tmp_path):
path=source_dir / "Some.Movie.2020.mkv",
filename="Some.Movie.2020.mkv",
size_bytes=1000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie"
)
@@ -814,7 +814,7 @@ def test_conflict_detection_with_multiple_files(config, tmp_path):
path=tmp_path / "movie" / "Movie1.2020.mkv",
filename="Movie1.2020.mkv",
size_bytes=1000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie"
),
MovieIdentity(
@@ -831,7 +831,7 @@ def test_conflict_detection_with_multiple_files(config, tmp_path):
path=tmp_path / "movie" / "Movie2.2021.mkv",
filename="Movie2.2021.mkv",
size_bytes=1000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie"
),
MovieIdentity(
@@ -864,7 +864,7 @@ def test_save_plan_to_json(config, tmp_path):
path=Path("/mnt/nas/videos/movie/Movie.2020.mkv"),
filename="Movie.2020.mkv",
size_bytes=1000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie"
)
@@ -909,7 +909,7 @@ def test_load_plan_from_json(config, tmp_path):
path=Path("/mnt/nas/videos/movie/Movie.2020.mkv"),
filename="Movie.2020.mkv",
size_bytes=1000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie"
)
@@ -963,7 +963,7 @@ def test_save_and_load_plan_with_conflicts(config, tmp_path):
path=tmp_path / "movie" / "Movie.2020.mkv",
filename="Movie.2020.mkv",
size_bytes=1000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie"
)
@@ -1003,7 +1003,7 @@ def test_save_and_load_plan_with_no_op_operations(config, tmp_path):
path=Path("/mnt/nas/videos/anime/Anime.01.mkv"),
filename="Anime.01.mkv",
size_bytes=500000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="anime"
),
None
@@ -1014,7 +1014,7 @@ def test_save_and_load_plan_with_no_op_operations(config, tmp_path):
path=Path("/mnt/nas/videos/movie/Movie.mkv"),
filename="Movie.mkv",
size_bytes=1000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie"
),
MovieIdentity(
@@ -1048,7 +1048,7 @@ def test_save_plan_json_is_human_readable(config, tmp_path):
path=Path("/mnt/nas/videos/movie/Movie.2020.mkv"),
filename="Movie.2020.mkv",
size_bytes=1000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie"
)
@@ -1089,7 +1089,7 @@ def test_save_plan_with_multiple_operations(config, tmp_path):
path=Path("/mnt/nas/videos/movie/Movie1.2020.mkv"),
filename="Movie1.2020.mkv",
size_bytes=1000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie"
),
MovieIdentity(
@@ -1106,7 +1106,7 @@ def test_save_plan_with_multiple_operations(config, tmp_path):
path=Path("/mnt/nas/videos/series/Show.S01E01.mkv"),
filename="Show.S01E01.mkv",
size_bytes=500000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="series"
),
SeriesIdentity(
@@ -1124,7 +1124,7 @@ def test_save_plan_with_multiple_operations(config, tmp_path):
path=Path("/mnt/nas/videos/anime/Anime.01.mkv"),
filename="Anime.01.mkv",
size_bytes=500000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="anime"
),
None
@@ -1176,7 +1176,7 @@ def test_plan_json_includes_all_required_fields(config, tmp_path):
path=Path("/mnt/nas/videos/movie/Movie.2020.mkv"),
filename="Movie.2020.mkv",
size_bytes=1000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie"
)
@@ -1214,7 +1214,7 @@ def test_movie_rejected_by_review_generates_noop(config):
path=Path("/mnt/nas/videos/movie/Movie.2020.mkv"),
filename="Movie.2020.mkv",
size_bytes=1000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="movie"
)
@@ -1238,7 +1238,7 @@ def test_series_rejected_by_review_generates_noop(config):
path=Path("/mnt/nas/videos/series/Show.S01E01.mkv"),
filename="Show.S01E01.mkv",
size_bytes=1000000,
modified_timestamp=datetime.now(),
modified_timestamp=datetime.now(timezone.utc),
category="series"
)