From 202733e10f32692e24739381d7c3a663c768d293 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 2 Nov 2026 18:55:42 +0000 Subject: [PATCH] fix: do not serve stale data from /data and /export When the data file does not exist (e.g. it was removed while the server was running), data() and export() kept returning the DataFrame left in memory from an earlier request. They now return "No data available." - Reset self.df to an empty DataFrame when the data file is missing - Add a test that removes the data file and checks both endpoints Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VCvw8haRnmyrVKrLkz5Yf8 --- succulent/processing.py | 6 ++++++ tests/test_succulent.py | 25 +++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/succulent/processing.py b/succulent/processing.py index f85ebd8..51486a5 100644 --- a/succulent/processing.py +++ b/succulent/processing.py @@ -344,6 +344,9 @@ def data(self, req): self.df = pd.read_xml(path) else: raise ValueError(f'Invalid file type: {self.format}') + else: + # No stored data (e.g. file removed): do not reuse stale data + self.df = pd.DataFrame() # Check if data is available if self.df.empty: @@ -390,6 +393,9 @@ def export(self, req): self.df = pd.read_xml(path) else: raise ValueError(f'Invalid file type: {self.format}') + else: + # No stored data (e.g. file removed): do not reuse stale data + self.df = pd.DataFrame() # Check if data is available if self.df.empty: diff --git a/tests/test_succulent.py b/tests/test_succulent.py index 13f9813..2bc9f2a 100644 --- a/tests/test_succulent.py +++ b/tests/test_succulent.py @@ -484,6 +484,31 @@ def test_data_and_export(self): ['temperature,humidity', '21.5,40', '22.0,45']) +class TestStaleData(unittest.TestCase): + """ + Test that /data and /export do not return stale in-memory data. + """ + + def setUp(self): + config_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'password.yml') + self.api = SucculentAPI(host='0.0.0.0', port=8080, config=config_path, format='csv') + self.client = self.api.app.test_client() + self.headers = {'X-API-Key': 's3cret'} + + def test_removed_data_file_is_not_served(self): + self.client.post('/measure', json={'temperature': 20}, headers=self.headers) + self.assertEqual(self.client.get('/data', headers=self.headers).status_code, 200) + + # Remove the stored data while the server keeps running + os.remove(os.path.join(self.api.processing.directory, 'data.csv')) + + for endpoint in ['/data', '/export']: + with self.subTest(endpoint=endpoint): + response = self.client.get(endpoint, headers=self.headers) + self.assertEqual(response.status_code, 400) + self.assertEqual(response.json['message'], 'No data available.') + + class TestConfiguration(unittest.TestCase): """ Test case for the Configuration class.