def test_load_metarecord(filetree): mr = MetaRecord.create_new(filetree.path) rec = Record(filetree.path, "Rec A", "Rec A Data") rec.save(mr) mr.save() newmr = MetaRecord.load_from(filetree.path) assert mr.path == newmr.path assert len(mr.records) == len(newmr.records) for i, r in enumerate(mr.records): assert r.name == newmr.records[i].name assert r.timestamp == newmr.records[i].timestamp
def test_create_record(filetree): mr = MetaRecord.create_new(filetree.path) new_rec_folder = "Rec A Data" new_rec_name = "Rec A" new_rec_full_path = os.path.join(record_folder, f"{new_rec_name}{record_ext}") rec = Record(filetree.path, new_rec_name, new_rec_folder) rec.save(mr) mr.save() assert filetree.exists(new_rec_full_path) assert len(filetree.content(new_rec_full_path)) > 0 assert filetree.exists(mr_path) assert len(filetree.content(mr_path)) > 0
def test_load_record(filetree): filetree.dir("source_data").file("junkA").file("junkB").build() mr = MetaRecord.create_new(filetree.path) rec = Record(filetree.path, "Rec A", "Rec A Data") rec.add_file(filetree.relpath("source_data/junkA"), filetree.relpath("source_data/junkA")) rec.add_file(filetree.relpath("source_data/junkB"), filetree.relpath("source_data/junkB")) rec.save(mr) mr.save() newrec = Record.load_from(rec.path, rec.name) assert rec == newrec
def _discover_directories(self): if os.path.exists(self.path): for dir in os.listdir(self.path): if dir == records.record_folder or not os.path.isdir( os.path.join(self.path, dir)): continue basename = dir.rstrip("/\\") ts = datetime.fromtimestamp( os.path.getctime(os.path.join(self.path, dir))) date_safe = ts.strftime('%Y-%m-%d_%H-%M-%S') self.directories.append([ Record(self.path, f"Backup for {date_safe}", basename, ts), True ])
def generate_diffs(self, data_queue: Queue): """ Calculate the change history of all backups for the metarecord this class was created with. Redundant files are collected and saved in `self.to_delete` :param data_queue: the queue to post updates to """ data_queue.put(AsyncUpdate("Loading Records...", 0, 1)) recs = [ Record.load_from(self.metarecord.path, r.name) for r in self.metarecord.records ] recs.sort(key=lambda r: r.timestamp) for i in range(len(recs) - 1): add, chg, rm, uchg = recs[i].file_diff(recs[i + 1]) if len(uchg) > 0: files = [] for item in uchg: files.append(item[1].file) item[1].source = item[0].source self.to_delete.append((recs[i + 1], files)) data_queue.put(AsyncUpdate("Diff complete!"))
def test_delete(filetree): filetree \ .dir("rec_a_data") \ .dir("Dir A") \ .file("tfa_1.txt", value="testfile_data_1") \ .file("tfa_2.txt", value="testfile_data_1") \ .up() \ .dir("Dir B") \ .file("tfb_1.txt", value="testfile_data_2") \ .root() \ .dir("rec_b_data") \ .dir("Dir A") \ .file("tfa_1.txt", value="testfile_data_1_chg") \ .file("tfa_2.txt", value="testfile_data_1") \ .up() \ .dir("Dir B") \ .file("tfb_1.txt", value="testfile_data_2") \ .build() mr = MetaRecord.create_new(filetree.path) recA = Record(filetree.path, "Rec A", "rec_a_data") recA.add_file(filetree.relpath("rec_a_data/Dir A/tfa_1.txt"), "Dir A/tfa_1.txt") recA.add_file(filetree.relpath("rec_a_data/Dir A/tfa_2.txt"), "Dir A/tfa_2.txt") recA.add_file(filetree.relpath("rec_a_data/Dir B/tfb_1.txt"), "Dir B/tfb_1.txt") recA.save(mr) recB = Record(filetree.path, "Rec B", "rec_b_data") recB.add_file(filetree.relpath("rec_b_data/Dir A/tfa_1.txt"), "Dir A/tfa_1.txt") recB.add_file(filetree.relpath("rec_b_data/Dir A/tfa_2.txt"), "Dir A/tfa_2.txt") recB.add_file(filetree.relpath("rec_b_data/Dir B/tfb_1.txt"), "Dir B/tfb_1.txt") recB.save(mr) mr.save() cln = Cleaner(mr) cln.generate_diffs() cln.wait_for_completion() cln.perform_clean() cln.wait_for_completion() assert os.path.exists(filetree.relpath("rec_a_data/Dir A/tfa_1.txt")) assert os.path.exists(filetree.relpath("rec_a_data/Dir A/tfa_2.txt")) assert os.path.exists(filetree.relpath("rec_a_data/Dir B/tfb_1.txt")) assert os.path.exists(filetree.relpath("rec_b_data/Dir A/tfa_1.txt")) assert not os.path.exists(filetree.relpath("rec_b_data/Dir A/tfa_2.txt")) assert not os.path.exists(filetree.relpath("rec_b_data/Dir B/tfb_1.txt"))
def test_generate_diffs(filetree): filetree \ .dir("rec_a_data") \ .dir("Dir A") \ .file("tfa_1.txt", value="testfile_data_1") \ .file("tfa_2.txt", value="testfile_data_1") \ .up() \ .dir("Dir B") \ .file("tfb_1.txt", value="testfile_data_2") \ .root() \ .dir("rec_b_data") \ .dir("Dir A") \ .file("tfa_1.txt", value="testfile_data_1_chg") \ .file("tfa_2.txt", value="testfile_data_1") \ .up() \ .dir("Dir B") \ .file("tfb_1.txt", value="testfile_data_2_chg") \ .build() mr = MetaRecord.create_new(filetree.path) recA = Record(filetree.path, "Rec A", "rec_a_data") recA.add_file(filetree.relpath("rec_a_data/Dir A/tfa_1.txt"), "Dir A/tfa_1.txt") recA.add_file(filetree.relpath("rec_a_data/Dir A/tfa_2.txt"), "Dir A/tfa_2.txt") recA.add_file(filetree.relpath("rec_a_data/Dir B/tfb_1.txt"), "Dir B/tfb_1.txt") recA.save(mr) recB = Record(filetree.path, "Rec B", "rec_b_data") recB.add_file(filetree.relpath("rec_b_data/Dir A/tfa_1.txt"), "Dir A/tfa_1.txt") recB.add_file(filetree.relpath("rec_b_data/Dir A/tfa_2.txt"), "Dir A/tfa_2.txt") recB.add_file(filetree.relpath("rec_b_data/Dir B/tfb_1.txt"), "Dir B/tfb_1.txt") recB.save(mr) mr.save() cln = Cleaner(mr) cln.generate_diffs() cln.wait_for_completion() diffs = cln.to_delete assert len(diffs) == 1 diff_rec, files = diffs[0] assert diff_rec.name == recB.name assert len(files) == 1 assert files[0] == "Dir A/tfa_2.txt"
def test_diff_records(filetree): filetree.dir("source_data") \ .file("junkA", deferred_content=["different things"]) \ .file("junkB", deferred_content=["different things B"]) \ .file("junkC") \ .build() mr = MetaRecord.create_new(filetree.path) rec = Record(filetree.path, "Rec A", "Rec A Data") rec.add_file(filetree.relpath("source_data/junkA"), filetree.relpath("source_data/junkA")) rec.add_file(filetree.relpath("source_data/junkB"), filetree.relpath("source_data/junkB")) rec.add_file(filetree.relpath("source_data/junkC"), filetree.relpath("source_data/junkC")) rec.save(mr) mr.save() filetree.root().do_deferred() rec2 = Record(filetree.path, "Rec A - 2", "Rec A Data") rec2.add_file(filetree.relpath("source_data/junkA"), filetree.relpath("source_data/junkA")) rec2.add_file(filetree.relpath("source_data/junkB"), filetree.relpath("source_data/junkB")) rec2.add_file(filetree.relpath("source_data/junkC"), filetree.relpath("source_data/junkC")) rec2.save(mr) mr.save() add, chg, rm, uchg = rec.file_diff(rec2) assert len(add) == 0 assert len(chg) == 2 assert len(rm) == 0 assert len(uchg) == 1 assert chg[0][1] == rec2.files[0] assert chg[1][1] == rec2.files[1]
def test_load_latest_record(filetree): # Records are timestamped on CREATION NOT SAVE. This test should reflect that the first to be *instantiated* # is the oldest, not the first to be saved! mr = MetaRecord.create_new(filetree.path) recA = Record(filetree.path, "Rec A", "Rec A Data") # Oldest sleep(2) recB = Record(filetree.path, "Rec B", "Rec B Data") # Newest recB.save(mr) recA.save(mr) mr.save() latest = mr.load_latest_record() assert latest == recB sleep(2) recC = Record(filetree.path, "Rec C", "Rec C Data") # New Newest recC.save(mr) mr.save() latest = mr.load_latest_record() assert latest == recC