From 339f7527388a911e7a9205cc67e4a1b4f745d044 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Wed, 21 Feb 2018 21:42:01 -0600 Subject: [PATCH 1/5] Added bitcoin donation addr --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index e4239da..d54f019 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,11 @@ Update the profile: python3 scripts/generate_profile.py /path/to/fit_sdk.zip fitparse/profile.py ``` +Donations +--------- + +You can donate to Bitcoin address: `1GAYJEWCGDaY1FbSfdD8W9Qzevu14UJTX6` + License ------- From 906fbe636a00dc0f63560a5648f475735fc59d4f Mon Sep 17 00:00:00 2001 From: Ondrej Medek Date: Sun, 25 Feb 2018 08:13:03 +0100 Subject: [PATCH 2/5] Add PyCharm .idea dir to .gitignore (#50) --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 1786a2f..749a4c4 100644 --- a/.gitignore +++ b/.gitignore @@ -53,5 +53,8 @@ docs/_build/ # PyBuilder target/ +# Various IDEs +/.idea + # python-fitparse specific FitSDK* From 3cd176df21c14c7434600f187fd7bcb5c2e2aede Mon Sep 17 00:00:00 2001 From: Ondrej Medek Date: Sun, 25 Feb 2018 22:35:51 +0100 Subject: [PATCH 3/5] Update README.md - FIT doc, ANT SDK link (#51) --- README.md | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index d54f019..b5ef37c 100644 --- a/README.md +++ b/README.md @@ -3,17 +3,26 @@ python-fitparse Here's a Python library to parse ANT/Garmin `.FIT` files. -Welcome to python-fitparse! After a few years of laying dormant we are back to -active development! The old version is archived as -[`v1-archive`](https://github.com/dtcooper/python-fitparse/releases/tag/v1-archive). - -The FIT (Flexible and Interoperable Data Transfer) file protocol is specified by -ANT (http://www.thisisant.com/) and an SDK is available for download at -http://www.thisisant.com/pages/products/fit-sdk. +Install from [![PyPI](https://img.shields.io/pypi/v/fitparse.svg)](https://pypi.python.org/pypi/fitparse/): +``` +pip install fitparse +``` +FIT files +------------ +- FIT files contain data stored in a binary file format. +- The FIT (Flexible and Interoperable Data Transfer) file protocol is specified + by [ANT](http://www.thisisant.com/). +- The SDK, code examples, and detailed documentation can be found in the + [ANT FIT SDK](http://www.thisisant.com/resources/fit). + Major Changes From Original Version ----------------------------------- +After a few years of laying dormant we are back to active development! +The old version is archived as +[`v1-archive`](https://github.com/dtcooper/python-fitparse/releases/tag/v1-archive). + * New, hopefully cleaner public API with a clear division between accessible and internal parts. (Still unstable and partially complete.) @@ -53,9 +62,8 @@ Major Changes From Original Version Updating to new FIT SDK versions -------------------------------- -Download the latest SDK from http://www.thisisant.com/pages/products/fit-sdk - -Update the profile: +- Download the latest [ANT FIT SDK](http://www.thisisant.com/resources/fit). +- Update the profile: ``` python3 scripts/generate_profile.py /path/to/fit_sdk.zip fitparse/profile.py ``` From 0de564fc4892e10604bcf2aeb6a9d9d5f2cf24a0 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Sun, 25 Feb 2018 22:48:03 -0500 Subject: [PATCH 4/5] Change bitcoin donation addr Change donation addr to be silly, but not offensive. Lapse in judgement. Thanks for pointing that out, @pR0Ps! --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b5ef37c..7d79657 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ python3 scripts/generate_profile.py /path/to/fit_sdk.zip fitparse/profile.py Donations --------- -You can donate to Bitcoin address: `1GAYJEWCGDaY1FbSfdD8W9Qzevu14UJTX6` +You can donate to Bitcoin address: `1PooPyStXWKZGUNqKYq3zNgTy6iutowaqp` License From adb103c8d07b9d5f3929c73f0b5e7f3ba04cfee6 Mon Sep 17 00:00:00 2001 From: Carey Metcalfe Date: Sun, 25 Feb 2018 23:46:57 -0500 Subject: [PATCH 5/5] Add JSON output option to fitdump script (#45) Other minor things: - Removed non-implemented output formats - Removed the restrction on dumping non-readable formats to stdout - Allow Python to buffer the output for faster execution Fixes #41 --- fitparse/__init__.py | 3 +- scripts/fitdump | 75 ++++++++++++++++++++++++++++++-------------- 2 files changed, 53 insertions(+), 25 deletions(-) diff --git a/fitparse/__init__.py b/fitparse/__init__.py index 49951b3..1bbc49e 100644 --- a/fitparse/__init__.py +++ b/fitparse/__init__.py @@ -1,9 +1,10 @@ from fitparse.base import FitFile, FitParseError +from fitparse.records import DataMessage from fitparse.processors import FitFileDataProcessor, StandardUnitsDataProcessor __version__ = '1.0.1' __all__ = [ 'FitFileDataProcessor', 'FitFile', 'FitParseError', - 'StandardUnitsDataProcessor', + 'StandardUnitsDataProcessor', 'DataMessage' ] diff --git a/scripts/fitdump b/scripts/fitdump index 95a7e76..5068456 100755 --- a/scripts/fitdump +++ b/scripts/fitdump @@ -1,7 +1,12 @@ #!/usr/bin/env python +from __future__ import print_function import argparse +import codecs +import datetime +import json import sys +import types # Python 2 compat try: @@ -13,20 +18,21 @@ except NameError: import fitparse -def format_message(message, options): - s = message.name +def format_message(num, message, options): + s = ["{}. {}".format(num, message.name)] if options.with_defs: - s += ' [%s]' % message.type - s += '\n' + s.append(' [{}]'.format(message.type)) + s.append('\n') if message.type == 'data': for field_data in message: - s += ' * %s: %s' % (field_data.name, field_data.value) + s.append(' * {}: {}'.format(field_data.name, field_data.value)) if field_data.units: - s += ' [%s]' % field_data.units - s += '\n' + s.append(' [{}]'.format(field_data.units)) + s.append('\n') - return s + s.append('\n') + return "".join(s) def parse_args(args=None): @@ -36,11 +42,12 @@ def parse_args(args=None): ) parser.add_argument('-v', '--verbose', action='count', default=0) parser.add_argument( - '-o', '--output', type=argparse.FileType(mode='wb'), - help='File to output to.', + '-o', '--output', type=argparse.FileType(mode='w'), default="-", + help='File to output data into (defaults to stdout)', ) parser.add_argument( - '-t', '--type', choices=('csv', 'excel', 'readable'), default='readable', + # TODO: csv + '-t', '--type', choices=('readable', 'json'), default='readable', help='File type to output. (DEFAULT: %(default)s)', ) parser.add_argument( @@ -56,20 +63,36 @@ def parse_args(args=None): options = parser.parse_args(args) - if (options.type != 'readable') and not options.output: - parser.error('Please specify an output file (-o) or set --type readable') + # Work around argparse.FileType not accepting an `encoding` kwarg in + # Python < 3.4 by closing and reopening the file (unless it's stdout) + if options.output is not sys.stdout: + options.output.close() + options.output = codecs.open(options.output.name, 'w', encoding='UTF-8') - options.with_defs = (options.verbose >= 1) - options.print_messages = (options.type == 'readable') - options.print_stream = (options.output or sys.stdout) - - if not options.print_messages and (options.verbose >= 1): - options.print_messages = True - options.print_stream = sys.stdout + options.verbose = options.verbose >= 1 + options.with_defs = (options.type == "readable" and options.verbose) + options.as_dict = (options.type != "readable" and options.verbose) return options +class RecordJSONEncoder(json.JSONEncoder): + def default(self, obj): + if isinstance(obj, types.GeneratorType): + return list(obj) + if isinstance(obj, datetime.datetime): + return obj.isoformat() + if isinstance(obj, fitparse.DataMessage): + return { + "type": obj.name, + "data": { + data.name: data.value for data in obj + } + } + # Fall back to original to raise a TypeError + return super(RecordJSONEncoder, self).default(obj) + + def main(args=None): options = parse_args(args) @@ -78,14 +101,18 @@ def main(args=None): data_processor=fitparse.StandardUnitsDataProcessor(), check_crc = not(options.ignore_crc), ) - messages = fitfile.get_messages( + records = fitfile.get_messages( name=options.name, with_definitions=options.with_defs, + as_dict=options.as_dict ) - for n, message in enumerate(messages, 1): - if options.print_messages: - print('{}. {}'.format(n, format_message(message, options), file=options.print_stream)) + if options.type == "json": + json.dump(records, fp=options.output, cls=RecordJSONEncoder) + elif options.type == "readable": + options.output.writelines(format_message(n, record, options) + for n, record in enumerate(records, 1)) + if __name__ == '__main__': try: