python-fitparse 2.1.7__tar.gz → 2.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-fitparse
3
- Version: 2.1.7
3
+ Version: 2.3.0
4
4
  Summary: Python library to parse ANT/Garmin .FIT files
5
5
  Project-URL: Homepage, https://github.com/nbr23/python-fitparse
6
6
  Project-URL: Repository, https://github.com/nbr23/python-fitparse
@@ -1,7 +1,8 @@
1
1
  # ***************** BEGIN AUTOMATICALLY GENERATED FIT PROFILE ******************
2
2
  # *************************** DO NOT EDIT THIS FILE ****************************
3
- # *********** EXPORTED PROFILE FROM SDK VERSION 21.205 ON 2026-05-20 ***********
4
- # ********* PARSED 201 TYPES (4399 VALUES), 124 MESSAGES (1411 FIELDS) *********
3
+ # *********** EXPORTED PROFILE FROM SDK VERSION 21.205 ON 2026-06-02 ***********
4
+ # ********* PARSED 201 TYPES (4399 VALUES), 124 MESSAGES (1412 FIELDS) *********
5
+ # ***************************** APPLIED 2 PATCHES ******************************
5
6
 
6
7
  from fitparse.records import (
7
8
  ComponentField,
@@ -11848,6 +11849,12 @@ MESSAGE_TYPES = {
11848
11849
  def_num=1,
11849
11850
  units='s',
11850
11851
  ),
11852
+ 3: Field( # Undocumented Garmin Body Battery level (0-100)
11853
+ name='body_battery',
11854
+ type=BASE_TYPES[0x01], # sint8
11855
+ def_num=3,
11856
+ units='percent',
11857
+ ),
11851
11858
  },
11852
11859
  ),
11853
11860
  229: MessageType(
@@ -0,0 +1,25 @@
1
+ # patches/message_types/stress_level.py
2
+ import sys
3
+ import os
4
+ sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', 'scripts'))
5
+ from generate_profile import MessageInfo, FieldInfo
6
+
7
+ MESSAGE_INFO = MessageInfo(
8
+ name='stress_level',
9
+ num=227,
10
+ group_name='',
11
+ fields=[
12
+ FieldInfo(
13
+ name='body_battery',
14
+ type='sint8',
15
+ num=3,
16
+ scale=None,
17
+ offset=None,
18
+ units='percent',
19
+ components=[],
20
+ subfields=[],
21
+ comment='Undocumented Garmin Body Battery level (0-100)'
22
+ ),
23
+ ],
24
+ comment=''
25
+ )
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "python-fitparse"
7
- version = "2.1.7"
7
+ version = "2.3.0"
8
8
  description = "Python library to parse ANT/Garmin .FIT files"
9
9
  authors = [
10
10
  {name = "David Cooper", email = "dave@kupesoft.com"},
@@ -318,6 +318,12 @@ class ReferenceFieldInfo(namedtuple('ReferenceFieldInfo', ('name', 'value', 'num
318
318
  return s
319
319
 
320
320
 
321
+ def normalize_def_num(num):
322
+ if isinstance(num, str):
323
+ return int(num, 16)
324
+ return num
325
+
326
+
321
327
  def render_comment(comment):
322
328
  if comment:
323
329
  return ' # %s' % comment
@@ -638,12 +644,15 @@ def load_field_type_patches():
638
644
 
639
645
  def apply_patches(type_list, message_list):
640
646
  print("Loading patches...")
647
+ applied = 0
648
+
641
649
  field_type_patches = load_field_type_patches()
642
650
  if field_type_patches:
643
651
  print(f"Applying {len(field_type_patches)} field type patches...")
644
652
  for patch_name, patch_type_info in field_type_patches.items():
645
653
  if not type_list.get(patch_name, raise_exception=False):
646
654
  type_list.types.append(patch_type_info)
655
+ applied += 1
647
656
  print(f" Added field type: {patch_name}")
648
657
  else:
649
658
  print(f" Skipped field type: {patch_name} (already exists in generated profile)")
@@ -660,9 +669,19 @@ def apply_patches(type_list, message_list):
660
669
 
661
670
  if not existing_message:
662
671
  message_list.messages.append(patch_message_info)
672
+ applied += 1
663
673
  print(f" Added message type: {patch_message_info.name} (num: {patch_num})")
664
674
  else:
665
- print(f" Skipped message type: {patch_message_info.name} (num: {patch_num}, already exists in generated profile)")
675
+ existing_nums = {normalize_def_num(f.num) for f in existing_message.fields}
676
+ for patch_field in patch_message_info.fields:
677
+ if normalize_def_num(patch_field.num) in existing_nums:
678
+ print(f" Skipped field: {existing_message.name}.{patch_field.name} (def_num {patch_field.num} already defined)")
679
+ else:
680
+ existing_message.fields.append(patch_field)
681
+ applied += 1
682
+ print(f" Added field: {existing_message.name}.{patch_field.name} (def_num {patch_field.num})")
683
+
684
+ return applied
666
685
 
667
686
 
668
687
  def download_latest_sdk(path):
@@ -734,7 +753,7 @@ def main(input_xls_or_zip, output_py_path=None):
734
753
  type_list = parse_types(types_rows)
735
754
  message_list = parse_messages(messages_rows, type_list)
736
755
 
737
- apply_patches(type_list, message_list)
756
+ patches_applied = apply_patches(type_list, message_list)
738
757
 
739
758
  mesg_num_declarations = []
740
759
  for mesg_name in MESSAGE_NUM_DECLARATIONS:
@@ -767,6 +786,7 @@ def main(input_xls_or_zip, output_py_path=None):
767
786
  len(type_list.types), sum(len(ti.values) for ti in type_list.types),
768
787
  len(message_list.messages), sum(len(mi.fields) for mi in message_list.messages),
769
788
  )),
789
+ header('APPLIED %d PATCH%s' % (patches_applied, '' if patches_applied == 1 else 'ES')),
770
790
  '', IMPORT_HEADER
771
791
  ]) + '\n'
772
792
 
File without changes