Simon Strandgaard
commited on
Commit
·
bb28e75
1
Parent(s):
977ad93
purge_old_runs() now also deletes files+dirs. Previously it was only dirs that could be purged.
Browse files- src/purge/purge_old_runs.py +13 -12
- src/purge/tests/test_purge_old_runs.py +24 -18
src/purge/purge_old_runs.py
CHANGED
@@ -9,7 +9,7 @@ logger = logging.getLogger(__name__)
|
|
9 |
|
10 |
def purge_old_runs(run_dir: str, max_age_hours: float = 1.0, prefix: str = "myrun_") -> None:
|
11 |
"""
|
12 |
-
Deletes
|
13 |
"""
|
14 |
if not os.path.isabs(run_dir):
|
15 |
raise ValueError(f"run_dir must be an absolute path: {run_dir}")
|
@@ -17,26 +17,27 @@ def purge_old_runs(run_dir: str, max_age_hours: float = 1.0, prefix: str = "myru
|
|
17 |
now = datetime.datetime.now()
|
18 |
cutoff = now - datetime.timedelta(hours=max_age_hours)
|
19 |
|
20 |
-
for
|
21 |
-
if not
|
22 |
continue # Skip files and directories that don't match the prefix
|
23 |
|
24 |
-
|
25 |
-
if not os.path.isdir(run_path):
|
26 |
-
continue # Skip files
|
27 |
|
28 |
try:
|
29 |
-
# Get the modification time of the directory
|
30 |
-
mtime = datetime.datetime.fromtimestamp(os.path.getmtime(
|
31 |
|
32 |
if mtime < cutoff:
|
33 |
-
logger.debug(f"Deleting old
|
34 |
-
|
|
|
|
|
|
|
35 |
else:
|
36 |
-
logger.debug(f"Skipping {
|
37 |
|
38 |
except Exception as e:
|
39 |
-
logger.error(f"Error processing {
|
40 |
|
41 |
def start_purge_scheduler(run_dir: str, purge_interval_seconds: float=3600, prefix: str = "myrun_") -> None:
|
42 |
"""
|
|
|
9 |
|
10 |
def purge_old_runs(run_dir: str, max_age_hours: float = 1.0, prefix: str = "myrun_") -> None:
|
11 |
"""
|
12 |
+
Deletes files and directories in the specified run_dir older than max_age_hours and matching the specified prefix.
|
13 |
"""
|
14 |
if not os.path.isabs(run_dir):
|
15 |
raise ValueError(f"run_dir must be an absolute path: {run_dir}")
|
|
|
17 |
now = datetime.datetime.now()
|
18 |
cutoff = now - datetime.timedelta(hours=max_age_hours)
|
19 |
|
20 |
+
for item in os.listdir(run_dir):
|
21 |
+
if not item.startswith(prefix):
|
22 |
continue # Skip files and directories that don't match the prefix
|
23 |
|
24 |
+
item_path = os.path.join(run_dir, item)
|
|
|
|
|
25 |
|
26 |
try:
|
27 |
+
# Get the modification time of the item (file or directory)
|
28 |
+
mtime = datetime.datetime.fromtimestamp(os.path.getmtime(item_path))
|
29 |
|
30 |
if mtime < cutoff:
|
31 |
+
logger.debug(f"Deleting old data: {item} from {run_dir}")
|
32 |
+
if os.path.isdir(item_path):
|
33 |
+
shutil.rmtree(item_path) # Delete the directory and all its contents
|
34 |
+
else:
|
35 |
+
os.remove(item_path) # Delete the file
|
36 |
else:
|
37 |
+
logger.debug(f"Skipping {item} in {run_dir}, last modified: {mtime}")
|
38 |
|
39 |
except Exception as e:
|
40 |
+
logger.error(f"Error processing {item} in {run_dir}: {e}")
|
41 |
|
42 |
def start_purge_scheduler(run_dir: str, purge_interval_seconds: float=3600, prefix: str = "myrun_") -> None:
|
43 |
"""
|
src/purge/tests/test_purge_old_runs.py
CHANGED
@@ -14,14 +14,16 @@ class TestPurgeOldRuns(unittest.TestCase):
|
|
14 |
os.makedirs(self.test_run_dir, exist_ok=True)
|
15 |
|
16 |
# Create some dummy run directories with different modification times
|
17 |
-
self.
|
18 |
-
self.
|
19 |
-
self.
|
20 |
-
self.
|
21 |
-
self.
|
22 |
-
self.
|
23 |
-
self.
|
24 |
-
self.create_dummy_file("
|
|
|
|
|
25 |
|
26 |
def tearDown(self):
|
27 |
"""Clean up test environment after each test."""
|
@@ -29,29 +31,33 @@ class TestPurgeOldRuns(unittest.TestCase):
|
|
29 |
if os.path.exists(self.test_run_dir):
|
30 |
shutil.rmtree(self.test_run_dir)
|
31 |
|
32 |
-
def
|
33 |
"""Creates a dummy run directory with a specific modification time."""
|
34 |
-
|
35 |
-
os.makedirs(
|
36 |
|
37 |
# Set the modification time of the directory
|
38 |
mtime = time.time() - (hours_old * 3600) # seconds
|
39 |
-
os.utime(
|
40 |
|
41 |
-
def create_dummy_file(self, filename):
|
42 |
"""Create a dummy file in the test directory."""
|
43 |
-
|
44 |
-
with open(
|
45 |
f.write("This is a dummy file.")
|
46 |
|
|
|
|
|
|
|
|
|
47 |
def test_purge_old_runs(self):
|
48 |
"""Tests the purge_old_runs function."""
|
49 |
max_age_hours = 0.95
|
50 |
purge_old_runs(self.test_run_dir, max_age_hours=max_age_hours, prefix="myrun_") # Pass the directory
|
51 |
|
52 |
# Check which runs should have been purged
|
53 |
-
runs_to_keep = ["
|
54 |
-
runs_to_purge = ["
|
55 |
|
56 |
for run_id in runs_to_keep:
|
57 |
run_path = os.path.join(self.test_run_dir, run_id)
|
@@ -74,7 +80,7 @@ class TestPurgeOldRuns(unittest.TestCase):
|
|
74 |
purge_old_runs(self.test_run_dir, max_age_hours=max_age_hours, prefix="myrun_") # Pass the directory
|
75 |
|
76 |
# All runs should still exist, including the one with the wrong prefix.
|
77 |
-
expected_runs = ["
|
78 |
for run_id in expected_runs:
|
79 |
run_path = os.path.join(self.test_run_dir, run_id)
|
80 |
self.assertTrue(os.path.exists(run_path), f"Run {run_id} should not have been purged.")
|
|
|
14 |
os.makedirs(self.test_run_dir, exist_ok=True)
|
15 |
|
16 |
# Create some dummy run directories with different modification times
|
17 |
+
self.create_dummy_dir("myrun_dir1", hours_old=0.5)
|
18 |
+
self.create_dummy_dir("myrun_dir2", hours_old=1.5)
|
19 |
+
self.create_dummy_dir("myrun_dir3", hours_old=2)
|
20 |
+
self.create_dummy_dir("myrun_dir4", hours_old=0.25)
|
21 |
+
self.create_dummy_dir("myrun_dir5", hours_old=1)
|
22 |
+
self.create_dummy_dir("myrun_dir6", hours_old=0)
|
23 |
+
self.create_dummy_dir("other_dir7", hours_old=1.5) # doesn't have the prefix, so don't delete
|
24 |
+
self.create_dummy_file("other_file.txt", hours_old=5) # doesn't have the prefix, so don't delete
|
25 |
+
self.create_dummy_file("myrun_file1.txt", hours_old=0.25)
|
26 |
+
self.create_dummy_file("myrun_file2.txt", hours_old=1.5)
|
27 |
|
28 |
def tearDown(self):
|
29 |
"""Clean up test environment after each test."""
|
|
|
31 |
if os.path.exists(self.test_run_dir):
|
32 |
shutil.rmtree(self.test_run_dir)
|
33 |
|
34 |
+
def create_dummy_dir(self, dirname: str, hours_old: float):
|
35 |
"""Creates a dummy run directory with a specific modification time."""
|
36 |
+
path = os.path.join(self.test_run_dir, dirname)
|
37 |
+
os.makedirs(path, exist_ok=True)
|
38 |
|
39 |
# Set the modification time of the directory
|
40 |
mtime = time.time() - (hours_old * 3600) # seconds
|
41 |
+
os.utime(path, (mtime, mtime))
|
42 |
|
43 |
+
def create_dummy_file(self, filename: str, hours_old: float):
|
44 |
"""Create a dummy file in the test directory."""
|
45 |
+
path = os.path.join(self.test_run_dir, filename)
|
46 |
+
with open(path, "w") as f:
|
47 |
f.write("This is a dummy file.")
|
48 |
|
49 |
+
# Set the modification time of the file
|
50 |
+
mtime = time.time() - (hours_old * 3600) # seconds
|
51 |
+
os.utime(path, (mtime, mtime))
|
52 |
+
|
53 |
def test_purge_old_runs(self):
|
54 |
"""Tests the purge_old_runs function."""
|
55 |
max_age_hours = 0.95
|
56 |
purge_old_runs(self.test_run_dir, max_age_hours=max_age_hours, prefix="myrun_") # Pass the directory
|
57 |
|
58 |
# Check which runs should have been purged
|
59 |
+
runs_to_keep = ["myrun_dir1", "myrun_dir4", "myrun_dir6", "other_dir7", "other_file.txt", "myrun_file1.txt"]
|
60 |
+
runs_to_purge = ["myrun_dir2", "myrun_dir3", "myrun_dir5", "myrun_file2.txt"]
|
61 |
|
62 |
for run_id in runs_to_keep:
|
63 |
run_path = os.path.join(self.test_run_dir, run_id)
|
|
|
80 |
purge_old_runs(self.test_run_dir, max_age_hours=max_age_hours, prefix="myrun_") # Pass the directory
|
81 |
|
82 |
# All runs should still exist, including the one with the wrong prefix.
|
83 |
+
expected_runs = ["myrun_dir1", "myrun_dir2", "myrun_dir3", "myrun_dir4", "myrun_dir5", "myrun_dir6", "other_dir7", "other_file.txt", "myrun_file1.txt", "myrun_file2.txt"]
|
84 |
for run_id in expected_runs:
|
85 |
run_path = os.path.join(self.test_run_dir, run_id)
|
86 |
self.assertTrue(os.path.exists(run_path), f"Run {run_id} should not have been purged.")
|