diff options
author | Daniel Schadt <kingdread@gmx.de> | 2025-04-21 00:58:33 +0200 |
---|---|---|
committer | Daniel Schadt <kingdread@gmx.de> | 2025-04-21 00:58:33 +0200 |
commit | 80ba8dac5f215a2bc7228cd3f3362f94b89e7ca6 (patch) | |
tree | 07244db261ff255b73a359acd74f7c5ba81e9609 | |
parent | 1dc76a03a00f631d45a7ad85838639387e924c5d (diff) | |
download | fietsboek-80ba8dac5f215a2bc7228cd3f3362f94b89e7ca6.tar.gz fietsboek-80ba8dac5f215a2bc7228cd3f3362f94b89e7ca6.tar.bz2 fietsboek-80ba8dac5f215a2bc7228cd3f3362f94b89e7ca6.zip |
cache & generate trackmap when uploading a track
-rw-r--r-- | fietsboek/actions.py | 12 | ||||
-rw-r--r-- | fietsboek/data.py | 29 | ||||
-rw-r--r-- | fietsboek/views/detail.py | 22 | ||||
-rw-r--r-- | fietsboek/views/upload.py | 2 | ||||
-rw-r--r-- | tests/playwright/conftest.py | 2 |
5 files changed, 61 insertions, 6 deletions
diff --git a/fietsboek/actions.py b/fietsboek/actions.py index a20ca2e..0457648 100644 --- a/fietsboek/actions.py +++ b/fietsboek/actions.py @@ -7,6 +7,7 @@ the test functions. """ import datetime +import io import logging import re from typing import Optional @@ -18,12 +19,12 @@ from pyramid.request import Request from sqlalchemy import select from sqlalchemy.orm.session import Session -from . import email, models +from . import email, models, trackmap, util from . import transformers as mod_transformers -from . import util from .data import DataManager, TrackDataDir from .models.track import TrackType, Visibility from .models.user import TokenType +from .views.tileproxy import TileRequester LOGGER = logging.getLogger(__name__) @@ -31,6 +32,7 @@ LOGGER = logging.getLogger(__name__) def add_track( dbsession: Session, data_manager: DataManager, + tile_requester: TileRequester, owner: models.User, title: str, date: datetime.datetime, @@ -105,6 +107,12 @@ def add_track( track.ensure_cache(gpx) dbsession.add(track.cache) + LOGGER.debug("Building preview image for %s", track.id) + preview_image = trackmap.render(gpx, tile_requester) + image_io = io.BytesIO() + preview_image.save(image_io, "PNG") + manager.set_preview(image_io.getvalue()) + manager.engrave_metadata( title=track.title, description=track.description, diff --git a/fietsboek/data.py b/fietsboek/data.py index a7e9b19..d1268bf 100644 --- a/fietsboek/data.py +++ b/fietsboek/data.py @@ -191,6 +191,12 @@ class TrackDataDir: elif action == "delete_image": path, data = rest path.write_bytes(data) + elif action == "set_preview": + old_data = rest + if old_data is None: + self.preview_path().unlink() + else: + self.preview_path().write_bytes(old_data) self.journal = None @@ -218,6 +224,9 @@ class TrackDataDir: elif action == "delete_image": # Again, nothing to do here, we simply discard the in-memory image data pass + elif action == "set_preview": + # Still nothing to do here + pass self.journal = None @@ -406,6 +415,26 @@ class TrackDataDir: path.unlink() + def preview_path(self) -> Path: + """Gets the path to the "preview image". + + :return: The path to the preview image. + """ + return self.path / "preview.png" + + def set_preview(self, data: bytes): + """Sets the preview image to the given data. + + :param data: The data of the preview image. + """ + if self.journal is not None: + try: + previous_preview = self.preview_path().read_bytes() + except FileNotFoundError: + previous_preview = None + self.journal.append(("set_preview", previous_preview)) + self.preview_path().write_bytes(data) + class UserDataDir: """Manager for a single user's data.""" diff --git a/fietsboek/views/detail.py b/fietsboek/views/detail.py index 332e107..0b42cdc 100644 --- a/fietsboek/views/detail.py +++ b/fietsboek/views/detail.py @@ -229,14 +229,28 @@ def add_comment(request): @view_config(route_name="track-map", http_cache=3600, permission="track.view") def track_map(request: Request): track = request.context + manager = request.data_manager.open(track.id) + preview_path = manager.preview_path() + try: + response = Response(preview_path.read_bytes(), content_type="image/png") + response.md5_etag() + return response + except FileNotFoundError: + pass + loader: ITileRequester = request.registry.getUtility(ITileRequester) - gpx = gpxpy.parse(request.data_manager.open(track.id).decompress_gpx()) + gpx = gpxpy.parse(manager.decompress_gpx()) image = trackmap.render(gpx, loader) - imagebytes = io.BytesIO() - image.save(imagebytes, "png") - response = Response(imagebytes.getvalue(), content_type="image/png") + imageio = io.BytesIO() + image.save(imageio, "png") + tile_data = imageio.getvalue() + + with manager.lock(): + manager.set_preview(tile_data) + + response = Response(tile_data, content_type="image/png") response.md5_etag() return response diff --git a/fietsboek/views/upload.py b/fietsboek/views/upload.py index c40319c..42dc59f 100644 --- a/fietsboek/views/upload.py +++ b/fietsboek/views/upload.py @@ -12,6 +12,7 @@ from sqlalchemy import select from .. import actions, convert, models, transformers, util from ..models.track import TrackType, Visibility +from ..views.tileproxy import ITileRequester LOGGER = logging.getLogger(__name__) @@ -165,6 +166,7 @@ def do_finish_upload(request): track = actions.add_track( request.dbsession, request.data_manager, + request.registry.getUtility(ITileRequester), owner=request.identity, title=request.params["title"], visibility=Visibility[request.params["visibility"]], diff --git a/tests/playwright/conftest.py b/tests/playwright/conftest.py index 4e7f5a4..205626d 100644 --- a/tests/playwright/conftest.py +++ b/tests/playwright/conftest.py @@ -11,6 +11,7 @@ from testutils import load_gpx_asset from fietsboek import models, util, actions from fietsboek.models.track import Visibility, TrackType from fietsboek.config import Config +from fietsboek.views.tileproxy import TileRequester import pytest @@ -117,6 +118,7 @@ class Helper: track = actions.add_track( self.dbaccess, self.data_manager, + TileRequester(None), owner=user, title="Another awesome track", visibility=Visibility.PRIVATE, |