Skip to content

Commit e45ee9c

Browse files
committed
Deprecate single-channel only methods, unify new methods
Add deprecation for purely single-channel only legacy methods, place new methods as reusable base methods, which can potentially be implemented in the future for single-channel as well. Signed-off-by: Pierre R. Mai <pmai@pmsf.de>
1 parent d5b70db commit e45ee9c

File tree

4 files changed

+78
-40
lines changed

4 files changed

+78
-40
lines changed

osi3trace/osi_trace.py

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import struct
88

99
from abc import ABC, abstractmethod
10+
from typing_extensions import deprecated
1011

1112
from mcap_protobuf.decoder import DecoderFactory
1213
from mcap.reader import make_reader
@@ -139,40 +140,38 @@ def __iter__(self):
139140
def close(self):
140141
return self.reader.close()
141142

143+
@deprecated("This is a legacy interface only supported for single-channel traces, which will be removed in future versions.")
142144
def retrieve_offsets(self, limit=None):
143145
if isinstance(self.reader, OSITraceSingle):
144146
return self.reader.retrieve_offsets(limit)
145147
raise NotImplementedError("Offsets are only supported for single-channel traces.")
146148

149+
@deprecated("This is a legacy interface only supported for single-channel traces, which will be removed in future versions.")
147150
def retrieve_message(self, index=None, skip=False):
148151
if isinstance(self.reader, OSITraceSingle):
149152
return self.reader.retrieve_message(index, skip)
150153
raise NotImplementedError("Index-based message retrieval is only supported for single-channel traces.")
151154

155+
@deprecated("This is a legacy interface only supported for single-channel traces, which will be removed in future versions.")
152156
def get_message_by_index(self, index):
153157
if isinstance(self.reader, OSITraceSingle):
154158
return self.reader.get_message_by_index(index)
155159
raise NotImplementedError("Index-based message retrieval is only supported for single-channel traces.")
156160

161+
@deprecated("This is a legacy interface only supported for single-channel traces, which will be removed in future versions.")
157162
def get_messages_in_index_range(self, begin, end):
158163
if isinstance(self.reader, OSITraceSingle):
159164
return self.reader.get_messages_in_index_range(begin, end)
160165
raise NotImplementedError("Index-based message retrieval is only supported for single-channel traces.")
161166

162167
def get_available_topics(self):
163-
if isinstance(self.reader, OSITraceMulti):
164-
return self.reader.get_available_topics()
165-
raise NotImplementedError("Getting available topics is only supported for multi-channel traces.")
168+
return self.reader.get_available_topics()
166169

167170
def get_file_metadata(self):
168-
if isinstance(self.reader, OSITraceMulti):
169-
return self.reader.get_file_metadata()
170-
raise NotImplementedError("Getting file metadata is only supported for multi-channel traces.")
171+
return self.reader.get_file_metadata()
171172

172173
def get_channel_metadata(self):
173-
if isinstance(self.reader, OSITraceMulti):
174-
return self.reader.get_channel_metadata()
175-
raise NotImplementedError("Getting channel metadata is only supported for multi-channel traces.")
174+
return self.reader.get_channel_metadata()
176175

177176

178177
class ReaderBase(ABC):
@@ -190,6 +189,18 @@ def __iter__(self):
190189
def close(self):
191190
pass
192191

192+
@abstractmethod
193+
def get_available_topics(self):
194+
pass
195+
196+
@abstractmethod
197+
def get_file_metadata(self):
198+
pass
199+
200+
@abstractmethod
201+
def get_channel_metadata(self):
202+
pass
203+
193204

194205
class OSITraceSingle(ReaderBase):
195206
"""OSI single-channel trace reader"""
@@ -203,21 +214,16 @@ def __init__(self, path=None, type_name="SensorView", cache_messages=False):
203214
self.message_cache = {} if cache_messages else None
204215
self._header_length = 4
205216
if path:
206-
self.from_file(path, type_name, cache_messages)
207-
208-
def from_file(self, path, type_name="SensorView", cache_messages=False):
209-
"""Import a trace from a file"""
210-
self.type = OSITrace.map_message_type(type_name)
217+
self.type = OSITrace.map_message_type(type_name)
211218

212-
if path.suffix.lower() in [".lzma", ".xz"]:
213-
self.file = lzma.open(path, "rb")
214-
else:
215-
self.file = open(path, "rb")
216-
217-
self.read_complete = False
218-
self.current_index = 0
219-
self.message_offsets = [0]
220-
self.message_cache = {} if cache_messages else None
219+
if path.suffix.lower() in [".lzma", ".xz"]:
220+
self.file = lzma.open(path, "rb")
221+
else:
222+
self.file = open(path, "rb")
223+
self.read_complete = False
224+
self.current_index = 0
225+
self.message_offsets = [0]
226+
self.message_cache = {} if cache_messages else None
221227

222228
def retrieve_offsets(self, limit=None):
223229
"""Retrieve the offsets of the messages from the file."""
@@ -337,6 +343,15 @@ def close(self):
337343
self.read_limit = None
338344
self.type = None
339345

346+
def get_available_topics(self):
347+
raise NotImplementedError("Getting available topics is only supported for multi-channel traces.")
348+
349+
def get_file_metadata(self):
350+
raise NotImplementedError("Getting file metadata is only supported for multi-channel traces.")
351+
352+
def get_channel_metadata(self):
353+
raise NotImplementedError("Getting channel metadata is only supported for multi-channel traces.")
354+
340355

341356
class OSITraceMulti(ReaderBase):
342357
"""OSI multi-channel trace reader"""
@@ -387,7 +402,7 @@ def get_channel_metadata(self):
387402
if channel.topic == self.topic:
388403
return channel.metadata
389404
return None
390-
405+
391406
def get_message_type(self):
392407
for channel in self._summary.channels.values():
393408
if channel.topic == self.topic:
@@ -397,7 +412,7 @@ def get_message_type(self):
397412
else:
398413
raise ValueError(f"Schema '{schema.name}' is not an 'osi3.' schema.")
399414
return None
400-
415+
401416
def _channel_is_of_type(self, channel, type_name):
402417
schema = self._summary.schemas[channel.schema_id]
403418
return type_name is None or schema.name == f"osi3.{type_name}"

poetry.lock

Lines changed: 2 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ readme = "README.md"
1212
dynamic = ["version"]
1313
requires-python = ">=3.10"
1414
dependencies = [
15+
"typing-extensions~=4.9",
1516
"protobuf>=6.30.2",
1617
"mcap>=1.2.2",
1718
"mcap-protobuf-support>=0.5.3"

tests/test_osi_trace.py

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os
22
import tempfile
33
import unittest
4+
import warnings
45

56
from osi3trace.osi_trace import OSITrace
67
from osi3.osi_sensorview_pb2 import SensorView
@@ -30,7 +31,9 @@ def test_osi_trace_sv(self):
3031
self.assertIsInstance(message, SensorView)
3132
f.write(str(message))
3233

33-
self.assertEqual(len(trace.retrieve_offsets()), 10)
34+
with warnings.catch_warnings():
35+
warnings.simplefilter("ignore")
36+
self.assertEqual(len(trace.retrieve_offsets()), 10)
3437
trace.close()
3538

3639
self.assertTrue(os.path.exists(path_output))
@@ -47,7 +50,9 @@ def test_osi_trace_svc(self):
4750
self.assertIsInstance(message, SensorViewConfiguration)
4851
f.write(str(message))
4952

50-
self.assertEqual(len(trace.retrieve_offsets()), 1)
53+
with warnings.catch_warnings():
54+
warnings.simplefilter("ignore")
55+
self.assertEqual(len(trace.retrieve_offsets()), 1)
5156
trace.close()
5257

5358
self.assertTrue(os.path.exists(path_output))
@@ -64,7 +69,9 @@ def test_osi_trace_gt(self):
6469
self.assertIsInstance(message, GroundTruth)
6570
f.write(str(message))
6671

67-
self.assertEqual(len(trace.retrieve_offsets()), 10)
72+
with warnings.catch_warnings():
73+
warnings.simplefilter("ignore")
74+
self.assertEqual(len(trace.retrieve_offsets()), 10)
6875
trace.close()
6976

7077
self.assertTrue(os.path.exists(path_output))
@@ -81,7 +88,9 @@ def test_osi_trace_hvd(self):
8188
self.assertIsInstance(message, HostVehicleData)
8289
f.write(str(message))
8390

84-
self.assertEqual(len(trace.retrieve_offsets()), 10)
91+
with warnings.catch_warnings():
92+
warnings.simplefilter("ignore")
93+
self.assertEqual(len(trace.retrieve_offsets()), 10)
8594
trace.close()
8695

8796
self.assertTrue(os.path.exists(path_output))
@@ -98,7 +107,9 @@ def test_osi_trace_sd(self):
98107
self.assertIsInstance(message, SensorData)
99108
f.write(str(message))
100109

101-
self.assertEqual(len(trace.retrieve_offsets()), 10)
110+
with warnings.catch_warnings():
111+
warnings.simplefilter("ignore")
112+
self.assertEqual(len(trace.retrieve_offsets()), 10)
102113
trace.close()
103114

104115
self.assertTrue(os.path.exists(path_output))
@@ -115,7 +126,9 @@ def test_osi_trace_tc(self):
115126
self.assertIsInstance(message, TrafficCommand)
116127
f.write(str(message))
117128

118-
self.assertEqual(len(trace.retrieve_offsets()), 10)
129+
with warnings.catch_warnings():
130+
warnings.simplefilter("ignore")
131+
self.assertEqual(len(trace.retrieve_offsets()), 10)
119132
trace.close()
120133

121134
self.assertTrue(os.path.exists(path_output))
@@ -132,7 +145,9 @@ def test_osi_trace_tcu(self):
132145
self.assertIsInstance(message, TrafficCommandUpdate)
133146
f.write(str(message))
134147

135-
self.assertEqual(len(trace.retrieve_offsets()), 10)
148+
with warnings.catch_warnings():
149+
warnings.simplefilter("ignore")
150+
self.assertEqual(len(trace.retrieve_offsets()), 10)
136151
trace.close()
137152

138153
self.assertTrue(os.path.exists(path_output))
@@ -149,7 +164,9 @@ def test_osi_trace_tu(self):
149164
self.assertIsInstance(message, TrafficUpdate)
150165
f.write(str(message))
151166

152-
self.assertEqual(len(trace.retrieve_offsets()), 10)
167+
with warnings.catch_warnings():
168+
warnings.simplefilter("ignore")
169+
self.assertEqual(len(trace.retrieve_offsets()), 10)
153170
trace.close()
154171

155172
self.assertTrue(os.path.exists(path_output))
@@ -166,7 +183,9 @@ def test_osi_trace_mr(self):
166183
self.assertIsInstance(message, MotionRequest)
167184
f.write(str(message))
168185

169-
self.assertEqual(len(trace.retrieve_offsets()), 10)
186+
with warnings.catch_warnings():
187+
warnings.simplefilter("ignore")
188+
self.assertEqual(len(trace.retrieve_offsets()), 10)
170189
trace.close()
171190

172191
self.assertTrue(os.path.exists(path_output))
@@ -183,7 +202,9 @@ def test_osi_trace_su(self):
183202
self.assertIsInstance(message, StreamingUpdate)
184203
f.write(str(message))
185204

186-
self.assertEqual(len(trace.retrieve_offsets()), 10)
205+
with warnings.catch_warnings():
206+
warnings.simplefilter("ignore")
207+
self.assertEqual(len(trace.retrieve_offsets()), 10)
187208
trace.close()
188209

189210
self.assertTrue(os.path.exists(path_output))
@@ -195,8 +216,10 @@ def test_osi_trace_offsets_robustness(self):
195216

196217
trace = OSITrace(path_input)
197218
# Test whether the function can handle be run multiple times safely
198-
offsets = trace.retrieve_offsets(None)
199-
offsets2 = trace.retrieve_offsets(None)
219+
with warnings.catch_warnings():
220+
warnings.simplefilter("ignore")
221+
offsets = trace.retrieve_offsets(None)
222+
offsets2 = trace.retrieve_offsets(None)
200223
trace.close()
201224

202225
self.assertEqual(len(offsets), 10)

0 commit comments

Comments
 (0)