diff options
author | Daniel Schadt <kingdread@gmx.de> | 2023-02-03 22:44:49 +0100 |
---|---|---|
committer | Daniel Schadt <kingdread@gmx.de> | 2023-02-03 22:44:49 +0100 |
commit | aebb3cb0bf39f47bd3c1cf44a2a3605405a2de59 (patch) | |
tree | a22515ab6c5c189a11dd9dfcd2c0156ef9db2e3e /fietsboek/actions.py | |
parent | b4ef0c0b9b60f817acb3405e0d317366abcd03c0 (diff) | |
download | fietsboek-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.py | 63 |
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 |