aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Schadt <kingdread@gmx.de>2025-11-09 18:23:30 +0100
committerDaniel Schadt <kingdread@gmx.de>2025-11-09 18:23:30 +0100
commitae55e81fd0c422eb4f1a232f0fcdc13c18022dbc (patch)
treed7953bb06c65dc89f32ccfa9c8ffabfc4b1c702b
parent0b26bb759f2b479a6a7b274a4e1436f62608dcf5 (diff)
downloadfietsboek-ae55e81fd0c422eb4f1a232f0fcdc13c18022dbc.tar.gz
fietsboek-ae55e81fd0c422eb4f1a232f0fcdc13c18022dbc.tar.bz2
fietsboek-ae55e81fd0c422eb4f1a232f0fcdc13c18022dbc.zip
better error handling for convert.smart_convert
Returning None is pretty nondescript, so let's make it official that we raise an exception there.
-rw-r--r--fietsboek/convert.py20
-rw-r--r--fietsboek/models/track.py2
-rw-r--r--fietsboek/views/edit.py6
3 files changed, 22 insertions, 6 deletions
diff --git a/fietsboek/convert.py b/fietsboek/convert.py
index 9cd3297..de6314f 100644
--- a/fietsboek/convert.py
+++ b/fietsboek/convert.py
@@ -12,6 +12,17 @@ from .models import Track, Waypoint
FIT_RECORD_FIELDS = ["position_lat", "position_long", "altitude", "timestamp"]
+class ConversionError(Exception):
+ """Error that occurred when loading a track from a file."""
+
+
+class UnknownFormat(ConversionError):
+ """The format of the source file could not be identified."""
+
+ def __str__(self):
+ return type(self).__doc__
+
+
def semicircles_to_deg(circles: int) -> float:
"""Convert semicircles coordinate to degree coordinate.
@@ -30,6 +41,7 @@ def from_fit(data: bytes) -> Track:
:param data: The input bytes.
:return: The converted structure.
+ :raises ConversionError: If conversion failed.
"""
fitfile = fitparse.FitFile(data)
start_time = None
@@ -68,6 +80,7 @@ def from_gpx(data: bytes) -> Track:
:param data: The input bytes.
:return: The converted structure.
+ :raises ConversionError: If conversion failed.
"""
# pylint: disable=too-many-locals
gpx = gpxpy.parse(data)
@@ -132,7 +145,7 @@ def from_gpx(data: bytes) -> Track:
return track
-def smart_convert(data: bytes) -> Optional[Track]:
+def smart_convert(data: bytes) -> Track:
"""Tries to be smart in converting the input bytes.
This function automatically applies the correct conversion if possible.
@@ -142,12 +155,13 @@ def smart_convert(data: bytes) -> Optional[Track]:
:param data: The input bytes.
:return: The converted content.
+ :raises ConversionError: When conversion fails.
"""
if len(data) > 11 and data[9:12] == b"FIT":
return from_fit(data)
if data.startswith(b"<?xml") and b"<gpx" in data[:200]:
return from_gpx(data)
- return None
+ raise UnknownFormat()
-__all__ = ["from_fit", "from_gpx", "smart_convert"]
+__all__ = ["ConversionError", "from_fit", "from_gpx", "smart_convert"]
diff --git a/fietsboek/models/track.py b/fietsboek/models/track.py
index c61c4e3..bd4bd15 100644
--- a/fietsboek/models/track.py
+++ b/fietsboek/models/track.py
@@ -395,7 +395,7 @@ class Track(Base):
:return: The GPS path of this track.
"""
return geo.Path(
- [point.to_geo_point() for point in sorted(self.points, key=lambda p: p.index)]
+ [point.to_geo_point() for point in sorted(self.points, key=lambda p: p.index or 0.0)]
)
def gpx_xml(self) -> bytes:
diff --git a/fietsboek/views/edit.py b/fietsboek/views/edit.py
index 4e7b1f5..a40b8c2 100644
--- a/fietsboek/views/edit.py
+++ b/fietsboek/views/edit.py
@@ -92,9 +92,11 @@ def do_edit(request):
pass
else:
LOGGER.info("Setting new track for %s", track.id)
- new_track = convert.smart_convert(gpx_bytes)
- if new_track is None:
+ try:
+ new_track = convert.smart_convert(gpx_bytes)
+ except convert.ConversionError as exc:
request.session.flash(request.localizer.translate(_("flash.invalid_file")))
+ LOGGER.info("Could not parse gpx: %s", exc)
return HTTPFound(request.route_url("edit", track_id=track.id))
data.compress_backup(gpx_bytes)
track.set_path(new_track.path())