1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 from __future__ import with_statement
36
37 """
38 YAML-based bag formats.
39 """
40
41
42
43
44
45 import collections
46 import yaml
47
48 import roslib.message
49
50 import rosh
51 from rosh.impl.exceptions import ROSHException
52 from rosh.impl.topic import TopicNS
53
54 -def create(msg_repr, type_, filename=None):
55 """
56 Create single message from YAML/dictionary representation.
57
58 @param type_: Message class
59 @type type_: class (Message subclass)
60 @param msg_repr: Message in string or dictionary representation
61 @type msg_repr: str or dict
62 @param filename: Name of file associated with msg_repr for debugging.
63 @type filename: str
64 """
65 if type(msg_repr) == str:
66 msg_repr = yaml.load(msg_repr)
67 if type(msg_repr) != dict:
68 if filename:
69 raise ValueError("msg_repr file [%s] does not contain a YAML dictionary"%filename)
70 else:
71 raise ValueError("msg_repr must contain a dictionary")
72 m = type_()
73
74 roslib.message.fill_message_args(m, [msg_repr])
75 return m
76
77 ZERO_STATE = 0
78 RECORD_STATE = 1
79 STOP_STATE = 2
80
82
83 - def __init__(self, name, stream, type_):
84 """
85 ctor.
86 """
87 self.name = name
88 self.type_ = type_
89 self._stream = stream
90 self._buff = None
91 self._yaml_iter = None
92 self.closed = False
93
94
95 self._state = ZERO_STATE
96 self._record = None
97
100
103
105 for doc in yaml.load_all(self._stream):
106 if doc is not None:
107 yield create(doc, self.type_)
108
110 """
111 Write message to bagy
112 @param msg: messsage to add
113 @type msg: self.type_
114 """
115 if not isinstance(msg, roslib.message.Message):
116 raise ValueError("msg is not a message instance")
117 self._stream.write(roslib.message.strify_message(msg) + '\n---\n')
118
120 """
121 Read *all* messages from bagy.
122
123 @return: messages
124 @rtype: [self.type_]
125 """
126 return [create(d, self.type_) for d in yaml.load_all(self._stream) if d is not None]
127
129 """
130 Get the next message in the bagy
131
132 @return: Message instance
133 @rtype: self.type_
134 """
135 if self._yaml_iter is None:
136 self._yaml_iter = yaml.load_all(self._stream)
137 v = self._yaml_iter.next()
138 if v is None:
139 return None
140 return create(v, self.type_)
141
143 """
144 Close resources associated with Bagy
145 """
146 self.closed = True
147 if self._state == RECORD_STATE:
148 self.stop()
149 self._state = ZERO_STATE
150 self._record = None
151
152 self._stream.close()
153 if self._yaml_iter is not None:
154 self._yaml_iter.close()
155
172
174 if self.closed:
175 raise ROSHException("closed")
176 if self._record is None:
177 raise ROSHException("not recording")
178 if self._state == STOP_STATE:
179 self._record._add_subscriber_callback(self.write)
180 self._state = RECORD_STATE
181
183 if self._record is None:
184 raise ROSHException("not recording")
185
186 if self._state == RECORD_STATE:
187 self._record._remove_subscriber_callback(self.write)
188 self._state = STOP_STATE
189
190
192 """
193 Bagy where messages are indexed by labels (keys).
194 """
195 - def __init__(self, name, stream, type_):
196 """
197 ctor.
198 """
199 self.name = name
200 self.type_ = type_
201 self._stream = stream
202 self._buff = None
203 self._db = None
204
207
210
212 if self._db is None:
213 self._load_db()
214 for key, d in self._db.iteritems():
215 yield key, create(d, self.type_)
216
217
219 if self._db is None:
220 self._load_db()
221 return key in self._db
222
223
225
226 return self.items().__eq__(other.items())
227
228
230
231 return self.items().__ne__(other.items())
232
233
235 if self._db is None:
236 self._load_db()
237 return self._db.keys()
238
239
241 return list(self.iteritems())
242
243
245 return list(self.itervalues())
246
248 if self._db is None:
249 self._load_db()
250 return self._db.iterkeys()
251
254
256 if self._db is None:
257 self._load_db()
258 for d in self._db.itervalues():
259 yield create(d, self.type_)
260
261 - def write(self, *args, **kwds):
262 """
263 write message into bagy. Must either pass in label and msg instance::
264
265 b.write('key', m)
266
267 or, pass in Python keywords, where keys are the labels::
268
269 b.write(key1=m1, key2=m2)
270 """
271 if args:
272 key, msg = args
273 if not isinstance(key, basestring):
274 raise TypeError("label must be a string")
275 if not isinstance(msg, roslib.message.Message):
276 raise ValueError("msg is not a message instance")
277 self._stream.write('%s:%s\n'%(key,
278 roslib.message.strify_message(msg, indent=' ')))
279 elif kwds:
280 for key, msg in kwds.iteritems():
281 if not isinstance(key, basestring):
282 raise TypeError("label must be a string")
283 if not isinstance(msg, roslib.message.Message):
284 raise ValueError("msg is not a message instance")
285 self._stream.write('%s:%s\n'%(key,
286 roslib.message.strify_message(msg, indent=' ')))
287 else:
288 raise TypeError("must provide an arguments or keywords to write()")
289
291 """
292 Load YAML dictionary into bagy instance. We don't convert the
293 dicts to messages until they are requested.
294 """
295 db = {}
296 for d in yaml.load_all(self._stream):
297 db.update(d)
298 self._stream.close()
299 self._db = db
300
302 """
303 Add item to label bagy as a map, e.g.::
304
305 b = keybagy('foo.bagy', 'w')
306 b[key] = msg
307 """
308 self.write(key, value)
309
310
311 - def get(self, key, default=None):
312 """
313 Get value from bagy, with optional default, e.g.::
314
315 b = keybagy('foo.bagy', 'r', msg.std_msgs.String)
316 msg = b.(key, altmsg)
317 """
318 if self._db is None:
319 self._load_db()
320 if key in self._db:
321 return create(self._db[key], self.type_)
322 else:
323 return default
324
325
327 if self._db is None:
328 self._load_db()
329 return self._db.__len__()
330
331
333 """
334 Access label bagy as a map, e.g.::
335
336 b = keybagy('foo.bagy', 'r', msg.std_msgs.String)
337 msg = b[key]
338 """
339 if self._db is None:
340 self._load_db()
341 return create(self._db[key], self.type_)
342
344 self._stream.close()
345 if self._db is not None:
346 del self._db
347
349 """
350 Read *all* messages from label bagy. This exhausts the bagy
351 and future methods that access data from the bagy will fail.
352
353 @return: messages
354 @rtype: dict{str: self.type_}
355 """
356 if self._db is None:
357 self._load_db()
358
359 retval = {}
360 for k, v in self._db.iteritems():
361 retval[k] = create(v, self.type_)
362 del self._db
363 self._db = None
364 return retval
365
366
367
369 - def __init__(self, filename, mode='r', type_=None):
370 """
371 @param filename: path to file
372 @type filename: str
373 @param mode: open mode. Valid modes are 'r' (read), 'w' (write), and 'a' (append).
374 @type mode: str
375 @param type_: Message type stored in bagy
376 @type type_: type(roslib.message.Message)
377 """
378 if mode in ['r', 'w', 'a']:
379 if mode == 'r' and type_ is None:
380 raise ValueError("type_ must be specified when reading from bagy files")
381 self.mode = mode
382 super(Bagy, self).__init__(filename, open(filename, mode), type_)
383 else:
384 raise ValueError("mode is invalid")
385
387 - def __init__(self, filename, mode, type_=None):
388 """
389 @param filename: path to file
390 @type filename: str
391 @param mode: open mode. Valid modes are 'r' (read), 'w' (write), and 'a' (append).
392 @type mode: str
393 @param type_: Message type stored in key bagy
394 @type type_: type(roslib.message.Message)
395 """
396 if mode in ['r', 'w', 'a']:
397 if mode == 'r' and type_ is None:
398 raise ValueError("type_ must be specified when reading from bagy files")
399 self.mode = mode
400 super(MapBagy, self).__init__(filename, open(filename, mode), type_)
401 else:
402 raise ValueError("mode is invalid")
403