11"""Tests for read() error signalling (Issue #390).
22
3- read() now returns (data, success_flag) and sets
4- concore.last_read_status / concore_base.last_read_status.
3+ read() returns data for backward compatibility.
4+ read_with_status() returns (data, success_flag).
5+ Both update concore.last_read_status / concore_base.last_read_status.
56"""
67
78import os
@@ -35,7 +36,7 @@ def recv_json_with_retry(self):
3536
3637
3738class TestReadFileSuccess :
38- """read () on a valid file returns (data, True) with SUCCESS status ."""
39+ """read_with_status () on a valid file returns (data, True)."""
3940
4041 @pytest .fixture (autouse = True )
4142 def setup (self , temp_dir , monkeypatch ):
@@ -53,7 +54,7 @@ def setup(self, temp_dir, monkeypatch):
5354 monkeypatch .setattr (concore , "inpath" , os .path .join (temp_dir , "in" ))
5455
5556 def test_returns_data_and_true (self ):
56- data , ok = self .concore .read (1 , "ym" , "[0, 0.0]" )
57+ data , ok = self .concore .read_with_status (1 , "ym" , "[0, 0.0]" )
5758 assert ok is True
5859 assert data == [3.14 ]
5960
@@ -63,7 +64,7 @@ def test_last_read_status_is_success(self):
6364
6465
6566class TestReadFileMissing :
66- """read () on a missing file returns (default, False) with FILE_NOT_FOUND ."""
67+ """read_with_status () on missing file returns (default, False)."""
6768
6869 @pytest .fixture (autouse = True )
6970 def setup (self , temp_dir , monkeypatch ):
@@ -75,7 +76,7 @@ def setup(self, temp_dir, monkeypatch):
7576 monkeypatch .setattr (concore , "inpath" , os .path .join (temp_dir , "in" ))
7677
7778 def test_returns_default_and_false (self ):
78- data , ok = self .concore .read (1 , "nonexistent" , "[0, 0.0]" )
79+ data , ok = self .concore .read_with_status (1 , "nonexistent" , "[0, 0.0]" )
7980 assert ok is False
8081
8182 def test_last_read_status_is_file_not_found (self ):
@@ -84,7 +85,7 @@ def test_last_read_status_is_file_not_found(self):
8485
8586
8687class TestReadFileParseError :
87- """read () returns (default, False) with PARSE_ERROR on malformed content ."""
88+ """read_with_status () returns (default, False) on parse errors ."""
8889
8990 @pytest .fixture (autouse = True )
9091 def setup (self , temp_dir , monkeypatch ):
@@ -101,7 +102,7 @@ def setup(self, temp_dir, monkeypatch):
101102 monkeypatch .setattr (concore , "inpath" , os .path .join (temp_dir , "in" ))
102103
103104 def test_returns_default_and_false (self ):
104- data , ok = self .concore .read (1 , "ym" , "[0, 0.0]" )
105+ data , ok = self .concore .read_with_status (1 , "ym" , "[0, 0.0]" )
105106 assert ok is False
106107
107108 def test_last_read_status_is_parse_error (self ):
@@ -110,7 +111,7 @@ def test_last_read_status_is_parse_error(self):
110111
111112
112113class TestReadFileTraversalBlocked :
113- """read () rejects traversal names and returns PARSE_ERROR."""
114+ """read_with_status () rejects traversal names and returns PARSE_ERROR."""
114115
115116 @pytest .fixture (autouse = True )
116117 def setup (self , temp_dir , monkeypatch ):
@@ -126,7 +127,7 @@ def setup(self, temp_dir, monkeypatch):
126127 f .write ("[10, 3.14]" )
127128
128129 def test_returns_default_and_false_on_traversal_name (self ):
129- data , ok = self .concore .read (1 , "../ym" , "[0, 0.0]" )
130+ data , ok = self .concore .read_with_status (1 , "../ym" , "[0, 0.0]" )
130131 assert ok is False
131132 assert data == [0 , 0.0 ]
132133
@@ -136,7 +137,7 @@ def test_last_read_status_is_parse_error_for_traversal_name(self):
136137
137138
138139class TestReadFileRetriesExceeded :
139- """read () returns (default, False) with RETRIES_EXCEEDED when file is empty ."""
140+ """read_with_status () returns (default, False) on retry exhaustion ."""
140141
141142 @pytest .fixture (autouse = True )
142143 def setup (self , temp_dir , monkeypatch ):
@@ -154,7 +155,7 @@ def setup(self, temp_dir, monkeypatch):
154155 monkeypatch .setattr (concore , "inpath" , os .path .join (temp_dir , "in" ))
155156
156157 def test_returns_default_and_false (self ):
157- data , ok = self .concore .read (1 , "ym" , "[0, 0.0]" )
158+ data , ok = self .concore .read_with_status (1 , "ym" , "[0, 0.0]" )
158159 assert ok is False
159160
160161 def test_last_read_status_is_retries_exceeded (self ):
@@ -168,7 +169,7 @@ def test_last_read_status_is_retries_exceeded(self):
168169
169170
170171class TestReadZMQSuccess :
171- """Successful ZMQ read returns (data, True)."""
172+ """Successful ZMQ read_with_status() returns (data, True)."""
172173
173174 @pytest .fixture (autouse = True )
174175 def setup (self , monkeypatch ):
@@ -185,14 +186,14 @@ def test_zmq_read_returns_data_and_true(self):
185186 self .concore .zmq_ports ["test_port" ] = dummy
186187 self .concore .simtime = 0
187188
188- data , ok = self .concore .read ("test_port" , "ym" , "[]" )
189+ data , ok = self .concore .read_with_status ("test_port" , "ym" , "[]" )
189190 assert ok is True
190191 assert data == [1.1 , 2.2 ]
191192 assert self .concore .last_read_status == "SUCCESS"
192193
193194
194195class TestReadZMQTimeout :
195- """ZMQ read that returns None ( timeout) yields (default, False)."""
196+ """ZMQ read timeout yields (default, False) via read_with_status( )."""
196197
197198 @pytest .fixture (autouse = True )
198199 def setup (self , monkeypatch ):
@@ -210,13 +211,13 @@ def test_zmq_timeout_returns_default_and_false(self):
210211 )
211212 self .concore .zmq_ports ["test_port" ] = dummy
212213
213- data , ok = self .concore .read ("test_port" , "ym" , "[]" )
214+ data , ok = self .concore .read_with_status ("test_port" , "ym" , "[]" )
214215 assert ok is False
215216 assert self .concore .last_read_status == "TIMEOUT"
216217
217218
218219class TestReadZMQError :
219- """ZMQ read that raises ZMQError yields (default, False)."""
220+ """ZMQ read ZMQError yields (default, False) via read_with_status( )."""
220221
221222 @pytest .fixture (autouse = True )
222223 def setup (self , monkeypatch ):
@@ -234,7 +235,7 @@ def test_zmq_error_returns_default_and_false(self):
234235 dummy = DummyZMQPort (raise_on_recv = zmq .error .ZMQError ("test error" ))
235236 self .concore .zmq_ports ["test_port" ] = dummy
236237
237- data , ok = self .concore .read ("test_port" , "ym" , "[]" )
238+ data , ok = self .concore .read_with_status ("test_port" , "ym" , "[]" )
238239 assert ok is False
239240 assert self .concore .last_read_status == "TIMEOUT"
240241
@@ -245,7 +246,7 @@ def test_zmq_error_returns_default_and_false(self):
245246
246247
247248class TestReadBackwardCompatibility :
248- """Legacy callers can use isinstance check on the result ."""
249+ """Legacy callers get plain data from read() ."""
249250
250251 @pytest .fixture (autouse = True )
251252 def setup (self , temp_dir , monkeypatch ):
@@ -261,22 +262,12 @@ def setup(self, temp_dir, monkeypatch):
261262
262263 monkeypatch .setattr (concore , "inpath" , os .path .join (temp_dir , "in" ))
263264
264- def test_legacy_unpack_pattern (self ):
265- """The recommended migration pattern works correctly."""
266- result = self .concore .read (1 , "ym" , "[0, 0.0]" )
267-
268- if isinstance (result , tuple ):
269- value , ok = result
270- else :
271- value = result
272- ok = True
273-
265+ def test_read_returns_data_only (self ):
266+ value = self .concore .read (1 , "ym" , "[0, 0.0]" )
274267 assert value == [42.0 ]
275- assert ok is True
276268
277- def test_tuple_unpack (self ):
278- """New-style callers can unpack directly."""
279- value , ok = self .concore .read (1 , "ym" , "[0, 0.0]" )
269+ def test_read_with_status_returns_tuple (self ):
270+ value , ok = self .concore .read_with_status (1 , "ym" , "[0, 0.0]" )
280271 assert value == [42.0 ]
281272 assert ok is True
282273
0 commit comments