Spaces:
Running
Running
File size: 8,996 Bytes
5f400f8 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | import pytest
from bot.sequence import MAX_LISTED, SeqItem, analyse, detect, format_report, ranges
def item(mid, name, caption=""):
return SeqItem(msg_id=mid, name=name, caption=caption)
def names(items):
return [i.name for i in items]
# ---------------------------------------------------------------------------
# reading the episode
# ---------------------------------------------------------------------------
@pytest.mark.parametrize(
"name,expected",
[
("1147 - One Piece [Dual] 720p @Anime_X_Universe.mkv", (1, 1147)),
("[SubsPlease] Tokyo Revengers - 05 (1080p) [ABCD1234].mkv", (1, 5)),
("Show.S02E14.720p.mkv", (2, 14)),
("Show 1x07.mkv", (1, 7)),
("One Piece [1146] 720p.mkv", (1, 1146)),
("Some Movie 2023 1080p.mkv", (None, None)),
("holiday video.mp4", (None, None)),
],
)
def test_detect_from_the_file_name(name, expected):
assert detect(name, "", "filename") == expected
def test_the_rename_mode_decides_which_source_is_read_first_and_the_other_is_the_fallback():
assert detect("Show S01E02.mkv", "Show S01E09", "filename") == (1, 2)
assert detect("Show S01E02.mkv", "Show S01E09", "caption") == (1, 9)
assert detect("random name.mkv", "One Piece - 1147", "filename") == (1, 1147) # nothing in the name: use the caption
assert detect("Show S01E02.mkv", "just words", "caption") == (1, 2) # nothing in the caption: use the name
assert detect("random.mkv", "", "caption") == (None, None)
# ---------------------------------------------------------------------------
# ordering
# ---------------------------------------------------------------------------
def test_files_come_out_in_ascending_episode_order_whatever_order_they_were_sent():
sent = [item(5, "1147 - One Piece.mkv"), item(6, "1145 - One Piece.mkv"), item(7, "1146 - One Piece.mkv"), item(8, "1148 - One Piece.mkv")]
a = analyse(sent, "filename")
assert names(a.ordered) == ["1145 - One Piece.mkv", "1146 - One Piece.mkv", "1147 - One Piece.mkv", "1148 - One Piece.mkv"]
assert a.missing == {} and a.repeated == {} and a.unknown == []
assert a.first == (1, 1145) and a.last == (1, 1148)
def test_episode_ten_sorts_after_nine_not_after_one():
a = analyse([item(1, "Show - 10.mkv"), item(2, "Show - 9.mkv"), item(3, "Show - 1.mkv"), item(4, "Show - 100.mkv")], "filename")
assert [i.episode for i in a.ordered] == [1, 9, 10, 100]
def test_seasons_sort_before_episodes():
sent = [item(1, "Show S02E01.mkv"), item(2, "Show S01E03.mkv"), item(3, "Show S01E01.mkv"), item(4, "Show S02E02.mkv")]
a = analyse(sent, "filename")
assert [(i.season, i.episode) for i in a.ordered] == [(1, 1), (1, 3), (2, 1), (2, 2)]
assert a.missing == {1: [2]} # S01E02 is missing; the jump from S01 to S02 is not a gap
assert a.first == (1, 1) and a.last == (2, 2)
def test_files_without_an_episode_number_go_last_in_the_order_they_were_sent():
sent = [item(9, "zzz.mkv"), item(3, "Show - 02.mkv"), item(4, "aaa.mkv"), item(2, "Show - 01.mkv")]
a = analyse(sent, "filename")
assert names(a.ordered) == ["Show - 01.mkv", "Show - 02.mkv", "aaa.mkv", "zzz.mkv"]
assert names(a.unknown) == ["aaa.mkv", "zzz.mkv"]
def test_nothing_is_numbered():
a = analyse([item(1, "b.mkv"), item(2, "a.mkv")], "filename")
assert names(a.ordered) == ["b.mkv", "a.mkv"] and a.first is None and a.last is None and a.missing == {}
# ---------------------------------------------------------------------------
# gaps and repeats
# ---------------------------------------------------------------------------
def test_missing_episodes_are_the_gaps_between_the_first_and_the_last():
sent = [item(i, f"One Piece - {n}.mkv") for i, n in enumerate((1145, 1146, 1148, 1151, 1152, 1156), start=1)]
a = analyse(sent, "filename")
assert a.missing == {1: [1147, 1149, 1150, 1153, 1154, 1155]}
# an episode before the first one you sent is not "missing"
assert analyse([item(1, "S - 5.mkv"), item(2, "S - 6.mkv")], "filename").missing == {}
assert analyse([item(1, "S - 5.mkv")], "filename").missing == {}
def test_repeated_episodes_list_every_file_that_shares_the_number():
sent = [item(1, "Show - 05 [A].mkv"), item(2, "Show - 05 [B].mkv"), item(3, "Show - 06.mkv"), item(4, "Show - 05 [C].mkv")]
a = analyse(sent, "filename")
assert list(a.repeated) == [(1, 5)] and names(a.repeated[(1, 5)]) == ["Show - 05 [A].mkv", "Show - 05 [B].mkv", "Show - 05 [C].mkv"]
assert names(a.ordered)[:3] == ["Show - 05 [A].mkv", "Show - 05 [B].mkv", "Show - 05 [C].mkv"] # both copies are kept, in send order
assert a.missing == {}
def test_the_same_episode_number_in_different_seasons_is_not_a_repeat():
a = analyse([item(1, "Show S01E01.mkv"), item(2, "Show S02E01.mkv")], "filename")
assert a.repeated == {}
def test_ranges():
assert ranges([3, 7, 8, 9]) == "E03, E07–E09"
assert ranges([1147]) == "E1147"
assert ranges([9, 3, 4]) == "E03–E04, E09"
assert ranges([]) == ""
# ---------------------------------------------------------------------------
# the report
# ---------------------------------------------------------------------------
def reports(files, mode="filename", failed=()):
sent = [item(i, n) for i, n in enumerate(files, start=1)]
a = analyse(sent, mode)
return format_report(a, len(sent), len(sent) - len(failed), [item(0, n) for n in failed])
def report(files, mode="filename", failed=()):
messages = reports(files, mode, failed)
assert len(messages) == 1
return messages[0]
def test_a_clean_sequence_says_so():
text = report(["One Piece - 1145.mkv", "One Piece - 1146.mkv", "One Piece - 1147.mkv"])
assert "Sorted 3 files" in text and "E1145 → E1147" in text and "No missing or repeated episodes." in text
assert "Missing" not in text and "Repeated" not in text
def test_files_without_a_number_do_not_hide_that_the_rest_is_complete():
text = report(["S - 01.mkv", "S - 02.mkv", "notes.mkv"])
assert "No missing or repeated episodes." in text and "No episode number found" in text
def test_nothing_numbered_means_nothing_to_say_about_gaps():
text = report(["a.mkv", "b.mkv"])
assert "No missing or repeated" not in text and "No episode number found" in text and "→" not in text
def test_one_file_is_not_plural():
assert "Sorted 1 file</b>" in report(["One Piece - 1145.mkv"])
def test_the_report_lists_missing_repeated_and_unnumbered_files():
text = report(["S - 01.mkv", "S - 02 a.mkv", "S - 02 b.mkv", "S - 05.mkv", "S - 08.mkv", "notes.mkv"])
assert "Sorted 6 files" in text and "E01 → E08" in text
assert "Missing episodes</b>\nE03–E04, E06–E07" in text
assert "Repeated episodes" in text and "E02 ×2" in text and "S - 02 a.mkv" in text and "S - 02 b.mkv" in text
assert "No episode number found" in text and "notes.mkv" in text
assert "No missing or repeated" not in text
def test_the_report_labels_seasons_only_when_there_are_several():
one = report(["S S01E01.mkv", "S S01E03.mkv"])
assert "E02" in one and "S01E02" not in one
two = report(["S S01E01.mkv", "S S01E03.mkv", "S S02E01.mkv", "S S02E02.mkv", "S S02E02 x.mkv"])
assert "S01: E02" in two and "S02E02 ×2" in two and "S01E01 → S02E02" in two
def test_the_report_mentions_files_that_could_not_be_sent():
text = report(["S - 01.mkv", "S - 02.mkv"], failed=["S - 02.mkv"])
assert "Sorted 1 of 2 files" in text and "Couldn't be sent" in text and "S - 02.mkv" in text
def test_names_are_escaped_and_long_lists_are_cut():
files = ["a&b <x>.mkv"] + [f"Dup {n}.mkv" for n in range(40)]
text = report(files)
assert "a&b <x>.mkv" in text and "<x>" not in text
assert "… and 29 more" in text and text.count("• ") == MAX_LISTED
def test_ranges_are_cut_when_there_are_too_many_gaps():
text = ranges(range(2, 2000, 2), limit=300)
assert len(text) <= 300 and text.endswith(" more") and text.startswith("E02, E04")
shown = text.count("E")
assert shown > 10
assert ranges([3, 7], limit=300) == "E03, E07"
def test_a_huge_report_is_split_into_messages_telegram_accepts():
files = []
files += [f"Long Running Show Name With A Rather Long Title - {n}.mkv" for n in range(1, 400, 2)] # 200 gaps
for n in range(1, 30): # many repeated numbers
files += [f"Another Show S02E{n:02d} [v{k}] with a very long name indeed.mkv" for k in range(5)]
files += [f"unknown file number {n} with quite a long name for a file.mkv" for n in range(50)]
messages = reports(files, failed=[f"deleted file {n}.mkv" for n in range(30)])
assert len(messages) > 1
assert all(len(m) <= 4000 for m in messages)
joined = "\n\n".join(messages)
assert "Missing episodes" in joined and "Repeated episodes" in joined and "No episode number found" in joined and "Couldn't be sent" in joined
assert messages[0].startswith("✅ <b>Sorted")
|