Skip to content

Commit bfb440a

Browse files
committed
FitFile API Cleanups
* Simpler API that can parse messages in a fit file on demand if treated as an iterator * Removed `get_messages_by_name()` method. Instead writing `get_messages(**kwargs)` that will be able query in a more flexible way. (WIP)
1 parent 0e1c63b commit bfb440a

2 files changed

Lines changed: 36 additions & 29 deletions

File tree

fitparse/base.py

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ def __init__(self, fileish, check_crc=True):
5151
self._accumulators = {}
5252
self._compressed_ts_accumulator = 0
5353
self._complete = False
54-
self.all_messages = [] # All messages including definitions
55-
self.messages = [] # Just data messages
54+
self._messages = []
5655

5756
# Start off by parsing the file header (makes self._data_bytes_left valid)
5857
self._parse_file_header()
@@ -135,13 +134,13 @@ def _parse_message(self):
135134
return None
136135

137136
header = self._parse_message_header()
137+
138138
if header.is_definition:
139139
message = self._parse_definition_message(header)
140140
else:
141141
message = self._parse_data_message(header)
142-
self.messages.append(message)
143-
self.all_messages.append(message)
144142

143+
self._messages.append(message)
145144
return message
146145

147146
def _parse_message_header(self):
@@ -359,40 +358,48 @@ def _parse_data_message(self, header):
359358
##########
360359
# Public API
361360

362-
def parse_one(self, as_dict=True, with_definitions=False):
363-
if with_definitions:
361+
def get_messages(
362+
self, name=None, mesg_num=None, has_field=None,
363+
with_definitions=False, as_dict=False,
364+
):
365+
# TODO: Implement the query arguments, also let them be tuples, ie name=('record', 'event')
366+
367+
if with_definitions: # with_definitions implies as_dict=False
364368
as_dict = False
365369

370+
def should_yield(message):
371+
if message and (with_definitions or message.type == 'data'):
372+
# If both args are None, then we return all
373+
if (name is None) and (mesg_num is None):
374+
return True
375+
if (name is not None) and name in (message.name, message.mesg_num):
376+
return True
377+
if (mesg_num is not None) and mesg_num == message.mesg_num:
378+
return True
379+
return False
380+
381+
# Yield all parsed messages first
382+
for message in self._messages:
383+
if should_yield(message):
384+
yield message.as_dict() if as_dict else message
385+
386+
# If there are unparsed messages, yield those too
366387
while not self._complete:
367388
message = self._parse_message()
368-
if message:
369-
if with_definitions or not message.header.is_definition:
370-
return message.as_dict() if as_dict else message
371-
372-
return None
389+
if message and should_yield(message):
390+
yield message.as_dict() if as_dict else message
373391

374-
def parse(self, as_dict=True, with_definitions=False):
375-
# if with_definitions:
376-
# as_dict = False
392+
@property
393+
def messages(self):
394+
# TODO: could this be more efficient?
395+
return list(self.get_messages())
377396

397+
def parse(self):
378398
while self._parse_message():
379399
pass
380400

381-
# TODO: abstract
382-
# return (
383-
# (msg.as_dict() if as_dict else msg)
384-
# for msg in self.messages
385-
# if with_definitions or msg.header.is_data
386-
# )
387-
388401
def __iter__(self):
389-
for message in self.messages:
390-
yield message
391-
392-
def get_messages_by_name(self, name, as_dict=True):
393-
for message in self.messages:
394-
if message.name == name:
395-
yield message.as_dict() if as_dict else message
402+
return self.get_messages()
396403

397404

398405
# TODO: Create subclasses like Activity and do per-value monkey patching

tests/test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ def test_component_field_accumulaters(self):
112112
f = FitFile(testfile('compressed-speed-distance.fit'))
113113
f.parse()
114114

115-
records = f.get_messages_by_name('record', as_dict=False)
115+
records = f.get_messages(name='record')
116116
empty_record = records.next() # Skip empty record for now (sets timestamp via header)
117117

118118
# File's timestamp record is < 0x10000000, so field returns seconds

0 commit comments

Comments
 (0)