aboutsummaryrefslogtreecommitdiff
path: root/fietsboek/actions.py
diff options
context:
space:
mode:
authorDaniel Schadt <kingdread@gmx.de>2023-02-03 22:44:49 +0100
committerDaniel Schadt <kingdread@gmx.de>2023-02-03 22:44:49 +0100
commitaebb3cb0bf39f47bd3c1cf44a2a3605405a2de59 (patch)
treea22515ab6c5c189a11dd9dfcd2c0156ef9db2e3e /fietsboek/actions.py
parentb4ef0c0b9b60f817acb3405e0d317366abcd03c0 (diff)
downloadfietsboek-aebb3cb0bf39f47bd3c1cf44a2a3605405a2de59.tar.gz
fietsboek-aebb3cb0bf39f47bd3c1cf44a2a3605405a2de59.tar.bz2
fietsboek-aebb3cb0bf39f47bd3c1cf44a2a3605405a2de59.zip
initial work on transformers
So far it doesn't really do much yet, but it does have the machinery to list the available transformers and run them. It also memorizes if the transformers even need to be run at all, to save time if the current configuration already matches. The parameter UI still needs some work. This is fine because the first transformer will not have any parameters (it's just the elevation fix). We probably don't want to have a method that returns Markup, as that makes it hard to implement localization in there, and the method would need to be aware of bootstrap. Another point to think about is documentation. I'd like some information for the user what the "transformers" are, so we'll probably add a small tagline and later extend the documentation with some more information (I want a user chapter in there at some point anyway).
Diffstat (limited to 'fietsboek/actions.py')
-rw-r--r--fietsboek/actions.py63
1 files changed, 60 insertions, 3 deletions
diff --git a/fietsboek/actions.py b/fietsboek/actions.py
index f1a32fc..350faaf 100644
--- a/fietsboek/actions.py
+++ b/fietsboek/actions.py
@@ -10,13 +10,15 @@ import logging
import re
from typing import List
+import brotli
+import gpxpy
from pyramid.request import Request
from sqlalchemy import select
from sqlalchemy.orm.session import Session
-from fietsboek import models, util
-from fietsboek.data import DataManager
-from fietsboek.models.track import TrackType, Visibility
+from . import models, transformers, util
+from .data import DataManager
+from .models.track import TrackType, Visibility
LOGGER = logging.getLogger(__name__)
@@ -154,3 +156,58 @@ def edit_images(request: Request, track: models.Track):
image_meta = models.ImageMetadata.get_or_create(request.dbsession, track, image_id)
image_meta.description = description
request.dbsession.add(image_meta)
+
+
+def execute_transformers(request: Request, track: models.Track):
+ """Execute the transformers for the given track.
+
+ Note that this function "short circuits" if the saved transformer settings
+ already match the settings given in the request.
+
+ :param request: The request.
+ :param track: The track.
+ """
+ # pylint: disable=too-many-locals
+ LOGGER.debug("Executing transformers for %d", track.id)
+
+ settings = []
+ for tfm in transformers.list_transformers():
+ ident = tfm.identifier()
+ prefix = f"transformer[{ident}]"
+ req_params = {}
+ for name, val in request.params.items():
+ if name.startswith(prefix):
+ name = name[len(prefix) :]
+ name = name.strip("[]")
+ req_params[name] = val
+
+ if req_params.get("") == "on":
+ params = tfm().parameters
+ params.read_from_request(req_params)
+ settings.append((ident, params))
+
+ serialized = [[tfm_id, params.dict()] for tfm_id, params in settings]
+ if serialized == track.transformers:
+ LOGGER.debug("Applied transformations mach on %d, skipping", track.id)
+ return
+
+ # We always start with the backup, that way we don't get "deepfried GPX"
+ # files by having the same filters run multiple times on the same input.
+ # They are not idempotent after all.
+ manager = request.data_manager.open(track.id)
+ gpx_bytes = manager.backup_path().read_bytes()
+ gpx_bytes = brotli.decompress(gpx_bytes)
+ gpx = gpxpy.parse(gpx_bytes)
+
+ tfms = {tfm.identifier(): tfm for tfm in transformers.list_transformers()}
+ for tfm_id, params in settings:
+ transformer = tfms[tfm_id]()
+ transformer.parameters = params
+ LOGGER.debug("Running %s with %r", transformer, params)
+ transformer.execute(gpx)
+
+ LOGGER.debug("Saving transformed file for %d", track.id)
+ manager.compress_gpx(gpx.to_xml().encode("utf-8"))
+
+ LOGGER.debug("Saving new transformers on %d", track.id)
+ track.transformers = serialized