diff --git a/frame/tracking/pulse.py b/frame/tracking/pulse.py index 47d87aa..deda229 100644 --- a/frame/tracking/pulse.py +++ b/frame/tracking/pulse.py @@ -89,7 +89,7 @@ class Capture: self.submitted = set() self.futures = {} self.new = set() # every capture directory that appeared during our run - self.before = set() + self.before = None # capture directories that existed before the run self.log = None def candidates(self): @@ -192,7 +192,8 @@ class Capture: def discard(self): """Delete the eye images written so far, without reading them.""" - self.new |= self.candidates() - self.before + if self.before is not None: + self.new |= self.candidates() - self.before for directory in self.new | ({self.directory} if self.directory else set()): if str(directory).startswith(self.PREFIX) and directory.is_dir() and not directory.is_symlink(): for entry in os.scandir(directory): @@ -259,6 +260,11 @@ class Capture: """Remove every capture directory that appeared during the run. Eye images must not outlive it, so a failure to delete is an error.""" left = [] + if self.before is not None: + try: + self.new |= self.candidates() - self.before # even if interrupted before the first poll + except OSError: + pass for directory in self.new | ({self.directory} if self.directory else set()): if str(directory).startswith(self.PREFIX) and directory.is_dir() and not directory.is_symlink(): try: diff --git a/scripts/heart-check.py b/scripts/heart-check.py index 048c429..9b3b05d 100644 --- a/scripts/heart-check.py +++ b/scripts/heart-check.py @@ -139,7 +139,7 @@ def read_health(path, start, end): try: when = parse_time(element.get("startDate") or "") value = round(float(element.get("value") or "")) - except ValueError: + except (ValueError, OverflowError): continue if start <= when <= end: samples.append((when, value)) diff --git a/tests/test_pulse.py b/tests/test_pulse.py index 31f55fd..fdd3208 100644 --- a/tests/test_pulse.py +++ b/tests/test_pulse.py @@ -339,6 +339,23 @@ class CaptureLifecycle(unittest.TestCase): self.assertIn("etcalib_a", str(raised.exception)) self.assertFalse(second.exists()) + def test_removes_a_directory_seen_only_at_the_end(self): + capture = pulse.Capture(20) + capture.PREFIX = str(self.root / "etcalib_") + capture.before = capture.candidates() + late = self.root / "etcalib_late" + late.mkdir() + (late / "left_0.png").write_bytes(b"png") + capture.remove() + self.assertFalse(late.exists()) + self.assertTrue((self.root / "etcalib_older").exists()) + + def test_never_adopts_directories_without_a_baseline(self): + capture = pulse.Capture(20) + capture.PREFIX = str(self.root / "etcalib_") + capture.remove() + self.assertTrue((self.root / "etcalib_older").exists()) + def test_only_removes_capture_directories(self): capture = pulse.Capture(20) capture.directory = self.root @@ -437,6 +454,12 @@ class HeartCheck(unittest.TestCase): str(self.write("bad.xml", "" + record % "inf" + record % "72" + "") + start = check.parse_time("2026-09-29 12:00:00 +1000") + self.assertEqual(check.read_health(path, start - 1, start + 1), [(start, 72)]) + def test_time_formats(self): self.assertEqual(check.parse_time("1700000000.5"), 1700000000.5) self.assertEqual(check.parse_time("2023-11-14T22:13:20Z"), 1700000000)