@@ -29,6 +29,12 @@ def _make_archive(tmp_path, mappings_dict, dry_run: bool = False):
2929 return archive
3030
3131
32+ def _record_source (archive , source_entry_ids ):
33+ for entry_id in source_entry_ids :
34+ archive .record_source_entry_id (entry_id = entry_id )
35+ return archive
36+
37+
3238def _mappings ():
3339 return {
3440 "id1" : DownloadMapping ("2024-01-01" , "yt" , {"a.mp4" }),
@@ -40,29 +46,33 @@ def _mappings():
4046class TestRemoveEntriesNotInSource :
4147 def test_entry_removed_from_source_is_pruned (self , tmp_path ):
4248 archive = _make_archive (tmp_path , _mappings ())
43- archive .remove_entries_not_in_source (source_entry_ids = {"id1" , "id3" })
49+ _record_source (archive , {"id1" , "id3" })
50+ archive .remove_entries_not_in_source ()
4451
4552 assert sorted (archive .mapping .entry_mappings .keys ()) == ["id1" , "id3" ]
4653 assert not (tmp_path / "output" / "b.mp4" ).exists ()
4754
4855 def test_entry_still_in_source_is_untouched (self , tmp_path ):
4956 archive = _make_archive (tmp_path , _mappings ())
50- archive .remove_entries_not_in_source (source_entry_ids = {"id1" , "id3" })
57+ _record_source (archive , {"id1" , "id3" })
58+ archive .remove_entries_not_in_source ()
5159
5260 assert (tmp_path / "output" / "a.mp4" ).exists ()
5361 assert (tmp_path / "output" / "c.mp4" ).exists ()
5462 assert archive .num_entries_removed == 1
5563
5664 def test_all_entries_in_source_removes_nothing (self , tmp_path ):
5765 archive = _make_archive (tmp_path , _mappings ())
58- archive .remove_entries_not_in_source (source_entry_ids = {"id1" , "id2" , "id3" })
66+ _record_source (archive , {"id1" , "id2" , "id3" })
67+ archive .remove_entries_not_in_source ()
5968
6069 assert sorted (archive .mapping .entry_mappings .keys ()) == ["id1" , "id2" , "id3" ]
6170 assert archive .num_entries_removed == 0
6271
6372 def test_source_with_new_entries_removes_nothing (self , tmp_path ):
6473 archive = _make_archive (tmp_path , _mappings ())
65- archive .remove_entries_not_in_source (source_entry_ids = {"id1" , "id2" , "id3" , "id4" })
74+ _record_source (archive , {"id1" , "id2" , "id3" , "id4" })
75+ archive .remove_entries_not_in_source ()
6676
6777 assert sorted (archive .mapping .entry_mappings .keys ()) == ["id1" , "id2" , "id3" ]
6878 assert archive .num_entries_removed == 0
@@ -77,16 +87,34 @@ def test_all_files_for_entry_are_deleted(self, tmp_path):
7787 "id2" : DownloadMapping ("2024-01-02" , "yt" , {"b.mp4" }),
7888 }
7989 archive = _make_archive (tmp_path , mappings )
80- archive .remove_entries_not_in_source (source_entry_ids = {"id2" })
90+ _record_source (archive , {"id2" })
91+ archive .remove_entries_not_in_source ()
8192
8293 for file_name in ("a.mp4" , "a.nfo" , "a-thumb.jpg" , "a.info.json" ):
8394 assert not (tmp_path / "output" / file_name ).exists ()
8495 assert (tmp_path / "output" / "b.mp4" ).exists ()
8596
8697 def test_dry_run_does_not_delete_files (self , tmp_path ):
8798 archive = _make_archive (tmp_path , _mappings (), dry_run = True )
88- archive .remove_entries_not_in_source (source_entry_ids = {"id1" , "id3" })
99+ _record_source (archive , {"id1" , "id3" })
100+ archive .remove_entries_not_in_source ()
101+
102+ assert (tmp_path / "output" / "b.mp4" ).exists ()
103+
104+ def test_unenumerated_source_deletes_nothing (self , tmp_path ):
105+ archive = _make_archive (tmp_path , _mappings ())
106+ archive .remove_entries_not_in_source ()
107+
108+ assert sorted (archive .mapping .entry_mappings .keys ()) == ["id1" , "id2" , "id3" ]
109+ assert (tmp_path / "output" / "b.mp4" ).exists ()
110+
111+ def test_truncated_source_deletes_nothing (self , tmp_path ):
112+ archive = _make_archive (tmp_path , _mappings ())
113+ _record_source (archive , {"id1" })
114+ archive .mark_source_enumeration_truncated (reason = "ExistingVideoReached" )
115+ archive .remove_entries_not_in_source ()
89116
117+ assert sorted (archive .mapping .entry_mappings .keys ()) == ["id1" , "id2" , "id3" ]
90118 assert (tmp_path / "output" / "b.mp4" ).exists ()
91119
92120
@@ -137,3 +165,23 @@ def test_accepts_override(self):
137165 def test_requires_maintain_download_archive (self ):
138166 with pytest .raises (ValidationException , match = "maintain_download_archive" ):
139167 OutputOptions ("t" , self ._base | {"sync_with_source" : True })
168+
169+ @pytest .mark .parametrize (
170+ "keep_option, keep_value" ,
171+ [
172+ ("keep_files_before" , "now" ),
173+ ("keep_files_after" , "19000101" ),
174+ ("keep_max_files" , 10 ),
175+ ],
176+ )
177+ def test_cannot_be_used_with_keep_options (self , keep_option , keep_value ):
178+ with pytest .raises (ValidationException , match = "cannot be used with" ):
179+ OutputOptions (
180+ "t" ,
181+ self ._base
182+ | {
183+ "maintain_download_archive" : True ,
184+ "sync_with_source" : True ,
185+ keep_option : keep_value ,
186+ },
187+ )
0 commit comments