make linter happy

This commit is contained in:
Laura Klünder 2024-02-07 18:34:28 +01:00
parent d7f175f7ef
commit 8c8ef12cf0
19 changed files with 107 additions and 75 deletions

View file

@ -9,14 +9,14 @@ from django.conf import settings
from django.core.cache import cache from django.core.cache import cache
from django.core.exceptions import FieldDoesNotExist from django.core.exceptions import FieldDoesNotExist
from django.core.serializers.json import DjangoJSONEncoder from django.core.serializers.json import DjangoJSONEncoder
from django.db.models import Q, Prefetch from django.db.models import Prefetch, Q
from django.forms import (BooleanField, CharField, ChoiceField, DecimalField, Form, JSONField, ModelChoiceField, from django.forms import (BooleanField, CharField, ChoiceField, DecimalField, Form, JSONField, ModelChoiceField,
ModelForm, MultipleChoiceField, Select, ValidationError) ModelForm, MultipleChoiceField, Select, ValidationError)
from django.forms.widgets import HiddenInput, TextInput from django.forms.widgets import HiddenInput, TextInput
from django.utils.translation import get_language from django.utils.translation import get_language
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from shapely.geometry.geo import mapping
from pydantic import ValidationError as PydanticValidationError from pydantic import ValidationError as PydanticValidationError
from shapely.geometry.geo import mapping
from c3nav.editor.models import ChangeSet, ChangeSetUpdate from c3nav.editor.models import ChangeSet, ChangeSetUpdate
from c3nav.mapdata.fields import GeometryField from c3nav.mapdata.fields import GeometryField
@ -40,12 +40,12 @@ class EditorFormBase(I18nModelFormMixin, ModelForm):
obstaclegroup_theme_colors = {} obstaclegroup_theme_colors = {}
else: else:
locationgroup_theme_colors = { locationgroup_theme_colors = {
l.location_group_id: l theme_location_group.location_group_id: theme_location_group
for l in self.instance.location_groups.filter(theme_id=self.instance.pk) for theme_location_group in self.instance.location_groups.filter(theme_id=self.instance.pk)
} }
obstaclegroup_theme_colors = { obstaclegroup_theme_colors = {
o.obstacle_group_id: o theme_obstacle.obstacle_group_id: theme_obstacle
for o in self.instance.obstacle_groups.filter(theme_id=self.instance.pk) for theme_obstacle in self.instance.obstacle_groups.filter(theme_id=self.instance.pk)
} }
# TODO: can we get the model class via relationships? # TODO: can we get the model class via relationships?
@ -54,15 +54,16 @@ class EditorFormBase(I18nModelFormMixin, ModelForm):
related = locationgroup_theme_colors.get(locationgroup.pk, None) related = locationgroup_theme_colors.get(locationgroup.pk, None)
value = related.fill_color if related is not None else None value = related.fill_color if related is not None else None
other_themes_colors = { other_themes_colors = {
l.title: l.fill_color theme_location_group.title: theme_location_group.fill_color
for l in locationgroup.theme_colors.all() for theme_location_group in locationgroup.theme_colors.all()
if related is None or l.pk != related.pk if related is None or theme_location_group.pk != related.pk
} }
if len(other_themes_colors) > 0: if len(other_themes_colors) > 0:
other_themes_colors = json.dumps(other_themes_colors) other_themes_colors = json.dumps(other_themes_colors)
else: else:
other_themes_colors = False other_themes_colors = False
field = CharField(max_length=32, field = CharField(
max_length=32,
label=locationgroup.title, label=locationgroup.title,
required=False, required=False,
initial=value, initial=value,
@ -375,7 +376,8 @@ class EditorFormBase(I18nModelFormMixin, ModelForm):
self.instance.groups.set(groups) self.instance.groups.set(groups)
if self._meta.model.__name__ == 'Theme': if self._meta.model.__name__ == 'Theme':
locationgroup_colors = {l.location_group_id: l for l in self.instance.location_groups.all()} locationgroup_colors = {theme_location_group.location_group_id: theme_location_group
for theme_location_group in self.instance.location_groups.all()}
for locationgroup in LocationGroup.objects.all(): for locationgroup in LocationGroup.objects.all():
value = self.cleaned_data[f'locationgroup_{locationgroup.pk}'] value = self.cleaned_data[f'locationgroup_{locationgroup.pk}']
if value: if value:

View file

@ -87,8 +87,10 @@ class GeometryField(models.JSONField):
def _validate_geomtype(self, value, exception: typing.Type[Exception] = ValidationError): def _validate_geomtype(self, value, exception: typing.Type[Exception] = ValidationError):
if not isinstance(value, self.classes): if not isinstance(value, self.classes):
# if you get this error with wrappedgeometry, looked into wrapped_geom # if you get this error with wrappedgeometry, looked into wrapped_geom
raise exception('Expected %s instance, got %s instead.' % (' or '.join(c.__name__ for c in self.classes), raise TypeError('Expected %s instance, got %s, %s instead.' % (
repr(value))) ' or '.join(c.__name__ for c in self.classes),
repr(value), value.wrapped_geom
))
def get_final_value(self, value, as_json=False): def get_final_value(self, value, as_json=False):
json_value = format_geojson(mapping(value)) json_value = format_geojson(mapping(value))

View file

@ -1,17 +1,15 @@
import hashlib import hashlib
import json
from uuid import UUID from uuid import UUID
import requests import requests
from django.conf import settings from django.conf import settings
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from pydantic import Field, BaseModel from pydantic import BaseModel, Field, PositiveInt
from pydantic import PositiveInt
from shapely import Point from shapely import Point
from shapely.geometry import shape from shapely.geometry import shape
from c3nav.api.utils import NonEmptyStr from c3nav.api.utils import NonEmptyStr
from c3nav.mapdata.models import Area, Space, LocationGroup, LocationSlug, MapUpdate from c3nav.mapdata.models import Area, LocationGroup, LocationSlug, MapUpdate, Space
from c3nav.mapdata.models.geometry.space import POI from c3nav.mapdata.models.geometry.space import POI
from c3nav.mapdata.models.report import Report from c3nav.mapdata.models.report import Report
from c3nav.mapdata.utils.cache.changes import changed_geometries from c3nav.mapdata.utils.cache.changes import changed_geometries
@ -189,7 +187,7 @@ class Command(BaseCommand):
if result.geometry != new_geometry or True: if result.geometry != new_geometry or True:
if result.import_block_geom: if result.import_block_geom:
geometry_needs_change.append(f"change geometry") geometry_needs_change.append("change geometry")
print(f"NOTE: {item.slug} / {item.id} geometry has changed but is blocked") print(f"NOTE: {item.slug} / {item.id} geometry has changed but is blocked")
else: else:
result.geometry = new_geometry result.geometry = new_geometry
@ -198,7 +196,7 @@ class Command(BaseCommand):
new_main_point = Point(item.location) if item.location else None new_main_point = Point(item.location) if item.location else None
if result.main_point != new_main_point: if result.main_point != new_main_point:
if result.import_block_geom: if result.import_block_geom:
geometry_needs_change.append(f"change main point") geometry_needs_change.append("change main point")
print(f"NOTE: {item.slug} / {item.id} main point has changed but is blocked") print(f"NOTE: {item.slug} / {item.id} main point has changed but is blocked")
else: else:
result.main_point = new_main_point result.main_point = new_main_point
@ -210,8 +208,8 @@ class Command(BaseCommand):
obj=item, obj=item,
report=Report( report=Report(
category="location-issue", category="location-issue",
title=f"importhub: geometry is blocked but needs changing", title="importhub: geometry is blocked but needs changing",
description=f"changes needed: "+','.join(geometry_needs_change), description="changes needed: "+','.join(geometry_needs_change),
location=result, location=result,
) )
) )
@ -278,8 +276,8 @@ class Command(BaseCommand):
obj=item, obj=item,
report=Report( report=Report(
category="location-issue", category="location-issue",
title=f"importhub: data is blocked but needs changing", title="importhub: data is blocked but needs changing",
description=f"changes needed: "+','.join(data_needs_change), description="changes needed: "+','.join(data_needs_change),
location=result, location=result,
) )
) )
@ -299,8 +297,8 @@ class Command(BaseCommand):
obj=item, obj=item,
report=Report( report=Report(
category="location-issue", category="location-issue",
title=f"importhub: location no longer has any valid group ids", title="importhub: location no longer has any valid group ids",
description=f"from the hub we would remove all groups, this seems wrong", description="from the hub we would remove all groups, this seems wrong",
location=result, location=result,
) )
) )
@ -326,8 +324,8 @@ class Command(BaseCommand):
obj=item, obj=item,
report=Report( report=Report(
category="location-issue", category="location-issue",
title=f"importhub: new groups", title="importhub: new groups",
description=(f"hub wants new groups for this, groups are now: " + description=("hub wants new groups for this, groups are now: " +
str([group.title for group in new_groups])), str([group.title for group in new_groups])),
location=result, location=result,
) )
@ -343,10 +341,9 @@ class Command(BaseCommand):
obj=import_tag, obj=import_tag,
report=Report( report=Report(
category="location-issue", category="location-issue",
title=f"importhub: delete this", title="importhub: delete this",
description=f"hub wants to delete this", description="hub wants to delete this",
location=location, location=location,
) )
) )
print(f"NOTE: {location.slug} / {import_tag} should be deleted") print(f"NOTE: {location.slug} / {import_tag} should be deleted")

View file

@ -1,3 +1,4 @@
import typing
from decimal import Decimal from decimal import Decimal
from django.conf import settings from django.conf import settings
@ -21,6 +22,9 @@ from c3nav.mapdata.utils.cache.changes import changed_geometries
from c3nav.mapdata.utils.geometry import unwrap_geom from c3nav.mapdata.utils.geometry import unwrap_geom
from c3nav.mapdata.utils.json import format_geojson from c3nav.mapdata.utils.json import format_geojson
if typing.TYPE_CHECKING:
from c3nav.mapdata.render.theme import ThemeColorManager
class SpaceGeometryMixin(GeometryMixin): class SpaceGeometryMixin(GeometryMixin):
space = models.ForeignKey('mapdata.Space', on_delete=models.CASCADE, verbose_name=_('space')) space = models.ForeignKey('mapdata.Space', on_delete=models.CASCADE, verbose_name=_('space'))
@ -240,7 +244,11 @@ class Obstacle(SpaceGeometryMixin, models.Model):
def get_color(self, color_manager: 'ThemeColorManager', instance=None): def get_color(self, color_manager: 'ThemeColorManager', instance=None):
if instance is None: if instance is None:
instance = self instance = self
return color_manager.obstaclegroup_fill_color(instance.group) if instance.group is not None else color_manager.obstacles_default_fill return (
color_manager.obstaclegroup_fill_color(instance.group)
if instance.group is not None
else color_manager.obstacles_default_fill
)
class LineObstacle(SpaceGeometryMixin, models.Model): class LineObstacle(SpaceGeometryMixin, models.Model):
@ -284,7 +292,11 @@ class LineObstacle(SpaceGeometryMixin, models.Model):
if instance is None: if instance is None:
instance = self instance = self
# TODO: should line obstacles use border color? # TODO: should line obstacles use border color?
return color_manager.obstaclegroup_fill_color(instance.group) if instance.group is not None else color_manager.obstacles_default_fill return (
color_manager.obstaclegroup_fill_color(instance.group)
if instance.group is not None
else color_manager.obstacles_default_fill
)
@property @property
def buffered_geometry(self): def buffered_geometry(self):

View file

@ -1,4 +1,5 @@
import string import string
import typing
from contextlib import suppress from contextlib import suppress
from datetime import timedelta from datetime import timedelta
from decimal import Decimal from decimal import Decimal
@ -25,6 +26,9 @@ from c3nav.mapdata.models.base import SerializableMixin, TitledMixin
from c3nav.mapdata.utils.fields import LocationById from c3nav.mapdata.utils.fields import LocationById
from c3nav.mapdata.utils.models import get_submodels from c3nav.mapdata.utils.models import get_submodels
if typing.TYPE_CHECKING:
from c3nav.mapdata.render.theme import ThemeColorManager
class LocationSlugManager(models.Manager): class LocationSlugManager(models.Manager):
def get_queryset(self): def get_queryset(self):

View file

@ -54,6 +54,7 @@ class ThemeObstacleGroupBackgroundColor(models.Model):
A background color for an ObstacleGroup in a theme A background color for an ObstacleGroup in a theme
""" """
theme = models.ForeignKey(Theme, on_delete=models.CASCADE, related_name="obstacle_groups") theme = models.ForeignKey(Theme, on_delete=models.CASCADE, related_name="obstacle_groups")
obstacle_group = models.ForeignKey(ObstacleGroup, on_delete=models.SET_NULL, null=True, blank=True, related_name="theme_colors") obstacle_group = models.ForeignKey(ObstacleGroup, on_delete=models.SET_NULL, null=True, blank=True,
related_name="theme_colors")
fill_color = models.CharField(max_length=32, null=True, blank=True) fill_color = models.CharField(max_length=32, null=True, blank=True)
border_color = models.CharField(max_length=32, null=True, blank=True) border_color = models.CharField(max_length=32, null=True, blank=True)

View file

@ -6,8 +6,7 @@ from itertools import chain
from typing import Literal, TypeVar from typing import Literal, TypeVar
import numpy as np import numpy as np
from matplotlib.patches import Polygon from shapely.geometry import GeometryCollection, LineString, MultiLineString, MultiPolygon, Point, Polygon
from shapely.geometry import GeometryCollection, LineString, MultiLineString, MultiPolygon, Point
from shapely.geometry.base import BaseGeometry from shapely.geometry.base import BaseGeometry
from shapely.ops import unary_union from shapely.ops import unary_union

View file

@ -1,4 +1,5 @@
import operator import operator
import typing
from collections import Counter, deque from collections import Counter, deque
from functools import reduce from functools import reduce
from itertools import chain from itertools import chain
@ -15,6 +16,9 @@ from c3nav.mapdata.utils.cache import AccessRestrictionAffected
from c3nav.mapdata.utils.geometry import get_rings, unwrap_geom from c3nav.mapdata.utils.geometry import get_rings, unwrap_geom
from c3nav.mapdata.utils.mesh import triangulate_rings from c3nav.mapdata.utils.mesh import triangulate_rings
if typing.TYPE_CHECKING:
from c3nav.mapdata.render.theme import ThemeColorManager
empty_geometry_collection = GeometryCollection() empty_geometry_collection = GeometryCollection()
@ -136,7 +140,9 @@ class LevelGeometries:
area.geometry = area.geometry.intersection(unwrap_geom(space.walkable_geom)) area.geometry = area.geometry.intersection(unwrap_geom(space.walkable_geom))
if access_restriction is not None: if access_restriction is not None:
access_restriction_affected.setdefault(access_restriction, []).append(area.geometry) access_restriction_affected.setdefault(access_restriction, []).append(area.geometry)
colors.setdefault(area.get_color_sorted(color_manager), {}).setdefault(access_restriction, []).append(area.geometry) colors.setdefault(
area.get_color_sorted(color_manager), {}
).setdefault(access_restriction, []).append(area.geometry)
for column in space.columns.all(): for column in space.columns.all():
access_restriction = column.access_restriction_id access_restriction = column.access_restriction_id
@ -162,7 +168,9 @@ class LevelGeometries:
for lineobstacle in space.lineobstacles.all(): for lineobstacle in space.lineobstacles.all():
if not lineobstacle.height: if not lineobstacle.height:
continue continue
obstacles.setdefault(int(lineobstacle.height*1000), {}).setdefault(lineobstacle.get_color(color_manager), []).append( obstacles.setdefault(int(lineobstacle.height*1000), {}).setdefault(
lineobstacle.get_color(color_manager), []
).append(
lineobstacle.buffered_geometry.intersection(unwrap_geom(space.walkable_geom)) lineobstacle.buffered_geometry.intersection(unwrap_geom(space.walkable_geom))
) )

View file

@ -85,7 +85,9 @@ class LevelRenderData:
altitudeareas_above = [] # todo: typing altitudeareas_above = [] # todo: typing
for render_level in reversed(levels): for render_level in reversed(levels):
# build level geometry for every single level # build level geometry for every single level
single_level_geoms[render_level.pk] = LevelGeometries.build_for_level(render_level, color_manager, altitudeareas_above) single_level_geoms[render_level.pk] = LevelGeometries.build_for_level(
render_level, color_manager, altitudeareas_above
)
# ignore intermediate levels in this pass # ignore intermediate levels in this pass
if render_level.on_top_of_id is not None: if render_level.on_top_of_id is not None:

View file

@ -11,7 +11,6 @@ from c3nav.mapdata.render.utils import get_full_levels, get_min_altitude
from c3nav.mapdata.utils.color import color_to_rgb, rgb_to_color from c3nav.mapdata.utils.color import color_to_rgb, rgb_to_color
class MapRenderer: class MapRenderer:
def __init__(self, level, minx, miny, maxx, maxy, scale=1, access_permissions=None, full_levels=False, def __init__(self, level, minx, miny, maxx, maxy, scale=1, access_permissions=None, full_levels=False,
min_width=None): min_width=None):

View file

@ -24,13 +24,13 @@ class ThemeColorManager:
self.obstacles_default_border = RENDER_COLOR_OBSTACLES_DEFAULT_BORDER self.obstacles_default_border = RENDER_COLOR_OBSTACLES_DEFAULT_BORDER
self.location_group_border_colors = {} self.location_group_border_colors = {}
self.location_group_fill_colors = { self.location_group_fill_colors = {
l.pk: l.color location_group.pk: location_group.color
for l in LocationGroup.objects.filter(color__isnull=False).all() for location_group in LocationGroup.objects.filter(color__isnull=False).all()
} }
self.obstacle_group_border_colors = {} self.obstacle_group_border_colors = {}
self.obstacle_group_fill_colors = { self.obstacle_group_fill_colors = {
o.pk: o.color obstacle_group.pk: obstacle_group.color
for o in ObstacleGroup.objects.filter(color__isnull=False).all() for obstacle_group in ObstacleGroup.objects.filter(color__isnull=False).all()
} }
else: else:
self.background = theme.color_background self.background = theme.color_background
@ -41,20 +41,20 @@ class ThemeColorManager:
self.obstacles_default_fill = theme.color_obstacles_default_fill self.obstacles_default_fill = theme.color_obstacles_default_fill
self.obstacles_default_border = theme.color_obstacles_default_border self.obstacles_default_border = theme.color_obstacles_default_border
self.location_group_border_colors = { self.location_group_border_colors = {
l.location_group_id: l.border_color theme_location_group.location_group_id: theme_location_group.border_color
for l in theme.location_groups.all() for theme_location_group in theme.location_groups.all()
} }
self.location_group_fill_colors = { self.location_group_fill_colors = {
l.location_group_id: l.fill_color theme_location_group.location_group_id: theme_location_group.fill_color
for l in theme.location_groups.all() for theme_location_group in theme.location_groups.all()
} }
self.obstacle_group_border_colors = { self.obstacle_group_border_colors = {
o.obstacle_group_id: o.border_color theme_obstacle_group.obstacle_group_id: theme_obstacle_group.border_color
for o in theme.obstacle_groups.all() for theme_obstacle_group in theme.obstacle_groups.all()
} }
self.obstacle_group_fill_colors = { self.obstacle_group_fill_colors = {
o.obstacle_group_id: o.fill_color theme_obstacle.obstacle_group_id: theme_obstacle.fill_color
for o in theme.obstacle_groups.all() for theme_obstacle in theme.obstacle_groups.all()
} }
def locationgroup_border_color(self, location_group: LocationGroup): def locationgroup_border_color(self, location_group: LocationGroup):

View file

@ -2,7 +2,7 @@ from django.urls import path, register_converter
from c3nav.mapdata.converters import (AccessPermissionsConverter, ArchiveFileExtConverter, HistoryFileExtConverter, from c3nav.mapdata.converters import (AccessPermissionsConverter, ArchiveFileExtConverter, HistoryFileExtConverter,
HistoryModeConverter, SignedIntConverter) HistoryModeConverter, SignedIntConverter)
from c3nav.mapdata.views import get_cache_package, map_history, tile, preview_location, preview_route from c3nav.mapdata.views import get_cache_package, map_history, preview_location, preview_route, tile
from c3nav.site.converters import LocationConverter from c3nav.site.converters import LocationConverter
register_converter(LocationConverter, 'loc') register_converter(LocationConverter, 'loc')
@ -16,7 +16,8 @@ urlpatterns = [
path('<int:level>/<sint:zoom>/<sint:x>/<sint:y>/<int:theme>.png', tile, name='mapdata.tile'), path('<int:level>/<sint:zoom>/<sint:x>/<sint:y>/<int:theme>.png', tile, name='mapdata.tile'),
path('preview/l/<loc:slug>.png', preview_location, name='mapdata.preview.location'), path('preview/l/<loc:slug>.png', preview_location, name='mapdata.preview.location'),
path('preview/r/<loc:slug>/<loc:slug2>.png', preview_route, name='mapdata.preview.route'), path('preview/r/<loc:slug>/<loc:slug2>.png', preview_route, name='mapdata.preview.route'),
path('<int:level>/<sint:zoom>/<sint:x>/<sint:y>/<int:theme>/<a_perms:access_permissions>.png', tile, name='mapdata.tile'), path('<int:level>/<sint:zoom>/<sint:x>/<sint:y>/<int:theme>/<a_perms:access_permissions>.png', tile,
name='mapdata.tile'),
path('history/<int:level>/<h_mode:mode>.<h_fileext:filetype>', map_history, name='mapdata.map_history'), path('history/<int:level>/<h_mode:mode>.<h_fileext:filetype>', map_history, name='mapdata.map_history'),
path('cache/package.<archive_fileext:filetype>', get_cache_package, name='mapdata.cache_package'), path('cache/package.<archive_fileext:filetype>', get_cache_package, name='mapdata.cache_package'),
] ]

View file

@ -51,5 +51,6 @@ def build_access_cache_key(access_permissions: set):
def build_tile_etag(level_id, zoom, x, y, theme_id, base_cache_key, access_cache_key, tile_secret): def build_tile_etag(level_id, zoom, x, y, theme_id, base_cache_key, access_cache_key, tile_secret):
# we want a short etag so HTTP 304 responses are tiny # we want a short etag so HTTP 304 responses are tiny
return '"' + binascii.b2a_base64(hashlib.sha256( return '"' + binascii.b2a_base64(hashlib.sha256(
('%d-%d-%d-%d:%s:%s:%s:%s' % (level_id, zoom, x, y, str(theme_id), base_cache_key, access_cache_key, tile_secret[:26])).encode() ('%d-%d-%d-%d:%s:%s:%s:%s' %
(level_id, zoom, x, y, str(theme_id), base_cache_key, access_cache_key, tile_secret[:26])).encode()
).digest()[:15], newline=False).decode() + '"' ).digest()[:15], newline=False).decode() + '"'

View file

@ -12,7 +12,7 @@ from django.http import Http404, HttpResponse, HttpResponseNotModified, Streamin
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from django.utils.http import content_disposition_header from django.utils.http import content_disposition_header
from django.views.decorators.http import etag from django.views.decorators.http import etag
from shapely import Point, box, LineString, unary_union from shapely import LineString, Point, box, unary_union
from c3nav.mapdata.middleware import no_language from c3nav.mapdata.middleware import no_language
from c3nav.mapdata.models import Level, MapUpdate from c3nav.mapdata.models import Level, MapUpdate
@ -345,7 +345,7 @@ def tile(request, level, zoom, x, y, theme, access_permissions: Optional[set] =
if not cache_package.bounds_valid(minx, miny, maxx, maxy): if not cache_package.bounds_valid(minx, miny, maxx, maxy):
raise Http404 raise Http404
theme = None if theme is 0 else int(theme) theme = None if theme == 0 else int(theme)
theme_key = str(theme) theme_key = str(theme)
# get level # get level
@ -372,7 +372,8 @@ def tile(request, level, zoom, x, y, theme, access_permissions: Optional[set] =
access_cache_key = build_access_cache_key(access_permissions) access_cache_key = build_access_cache_key(access_permissions)
# check browser cache # check browser cache
tile_etag = build_tile_etag(level, zoom, x, y, theme_key, base_cache_key, access_cache_key, settings.SECRET_TILE_KEY) tile_etag = build_tile_etag(level, zoom, x, y, theme_key, base_cache_key, access_cache_key,
settings.SECRET_TILE_KEY)
if_none_match = request.META.get('HTTP_IF_NONE_MATCH') if_none_match = request.META.get('HTTP_IF_NONE_MATCH')
if if_none_match == tile_etag: if if_none_match == tile_etag:
return HttpResponseNotModified() return HttpResponseNotModified()

View file

@ -1,5 +1,5 @@
from enum import StrEnum from enum import StrEnum
from typing import Annotated, Optional, Union, Any from typing import Annotated, Any, Optional, Union
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.urls import reverse from django.urls import reverse

View file

@ -361,7 +361,7 @@ MIDDLEWARE = [
'c3nav.mapdata.middleware.UserDataMiddleware', 'c3nav.mapdata.middleware.UserDataMiddleware',
'c3nav.site.middleware.MobileclientMiddleware', 'c3nav.site.middleware.MobileclientMiddleware',
'c3nav.control.middleware.UserPermissionsMiddleware', 'c3nav.control.middleware.UserPermissionsMiddleware',
#'c3nav.api.middleware.JsonRequestBodyMiddleware', # might still be needed in editor # 'c3nav.api.middleware.JsonRequestBodyMiddleware', # might still be needed in editor
] ]
with suppress(ImportError): with suppress(ImportError):

View file

@ -2,7 +2,7 @@ from itertools import chain
from django.urls import path, register_converter from django.urls import path, register_converter
from c3nav.site.converters import AtPositionConverter, CoordinatesConverter, IsEmbedConverter, LocationConverter from c3nav.site.converters import AtPositionConverter, CoordinatesConverter, IsEmbedConverter
from c3nav.site.views import (about_view, access_redeem_view, account_manage, account_view, api_secret_create, from c3nav.site.views import (about_view, access_redeem_view, account_manage, account_view, api_secret_create,
api_secret_list, change_password_view, choose_language, delete_account_view, login_view, api_secret_list, change_password_view, choose_language, delete_account_view, login_view,
logout_view, map_index, position_create, position_detail, position_list, position_set, logout_view, map_index, position_create, position_detail, position_list, position_set,
@ -18,13 +18,15 @@ pos = '<at_pos:pos>'
def index_paths(pre, suf): def index_paths(pre, suf):
return [ return [
path(f'{pre}l/<loc:slug>/{suf}', map_index, {'mode': 'l', 'details': False, 'nearby': False}, name='site.index', ), path(f'{pre}l/<loc:slug>/{suf}', map_index, {'mode': 'l', 'details': False, 'nearby': False},
name='site.index'),
path(f'{pre}l/<loc:slug>/details/{suf}', map_index, {'mode': 'l', 'details': True}, name='site.index'), path(f'{pre}l/<loc:slug>/details/{suf}', map_index, {'mode': 'l', 'details': True}, name='site.index'),
path(f'{pre}l/<loc:slug>/nearby/{suf}', map_index, {'mode': 'l', 'nearby': True}, name='site.index'), path(f'{pre}l/<loc:slug>/nearby/{suf}', map_index, {'mode': 'l', 'nearby': True}, name='site.index'),
path(f'{pre}o/<loc:slug>/{suf}', map_index, {'mode': 'o'}, name='site.index'), path(f'{pre}o/<loc:slug>/{suf}', map_index, {'mode': 'o'}, name='site.index'),
path(f'{pre}d/<loc:slug>/{suf}', map_index, {'mode': 'd'}, name='site.index'), path(f'{pre}d/<loc:slug>/{suf}', map_index, {'mode': 'd'}, name='site.index'),
path(f'{pre}r/{suf}', map_index, {'mode': 'r'}, name='site.index'), path(f'{pre}r/{suf}', map_index, {'mode': 'r'}, name='site.index'),
path(f'{pre}r/<loc:slug>/<loc:slug2>/{suf}', map_index, {'mode': 'r', 'details': False, 'options': False}, name='site.index'), path(f'{pre}r/<loc:slug>/<loc:slug2>/{suf}', map_index, {'mode': 'r', 'details': False, 'options': False},
name='site.index'),
path(f'{pre}r/<loc:slug>/<loc:slug2>/details/{suf}', map_index, {'mode': 'r', 'details': True}, path(f'{pre}r/<loc:slug>/<loc:slug2>/details/{suf}', map_index, {'mode': 'r', 'details': True},
name='site.index'), name='site.index'),
path(f'{pre}r/<loc:slug>/<loc:slug2>/options/{suf}', map_index, {'mode': 'r', 'options': True}, path(f'{pre}r/<loc:slug>/<loc:slug2>/options/{suf}', map_index, {'mode': 'r', 'options': True},

View file

@ -29,7 +29,7 @@ from c3nav import __version__ as c3nav_version
from c3nav.api.models import Secret from c3nav.api.models import Secret
from c3nav.mapdata.grid import grid from c3nav.mapdata.grid import grid
from c3nav.mapdata.models import Location, Source from c3nav.mapdata.models import Location, Source
from c3nav.mapdata.models.access import AccessPermissionToken, AccessPermission from c3nav.mapdata.models.access import AccessPermission, AccessPermissionToken
from c3nav.mapdata.models.locations import LocationRedirect, Position, SpecificLocation, get_position_secret from c3nav.mapdata.models.locations import LocationRedirect, Position, SpecificLocation, get_position_secret
from c3nav.mapdata.models.report import Report, ReportUpdate from c3nav.mapdata.models.report import Report, ReportUpdate
from c3nav.mapdata.utils.locations import (get_location_by_id_for_request, get_location_by_slug_for_request, from c3nav.mapdata.utils.locations import (get_location_by_id_for_request, get_location_by_slug_for_request,

View file

@ -188,7 +188,7 @@ class TileServer:
error = False error = False
try: try:
last_check = self.cache.get('cache_package_last_successful_check') last_check = self.cache.get('cache_package_last_successful_check')
except pylibmc.Error as e: except pylibmc.Error:
error = True error = True
text = b'memcached error' text = b'memcached error'
else: else:
@ -300,7 +300,8 @@ class TileServer:
if cached_result is not None: if cached_result is not None:
return self.deliver_tile(start_response, tile_etag, cached_result) return self.deliver_tile(start_response, tile_etag, cached_result)
r = requests.get('%s/map/%d/%d/%d/%d/%d/%s.png' % (self.upstream_base, level, zoom, x, y, theme_id, access_cache_key), r = requests.get('%s/map/%d/%d/%d/%d/%d/%s.png' %
(self.upstream_base, level, zoom, x, y, theme_id, access_cache_key),
headers=self.auth_headers, auth=self.http_auth) headers=self.auth_headers, auth=self.http_auth)
if r.status_code == 200 and r.headers['Content-Type'] == 'image/png': if r.status_code == 200 and r.headers['Content-Type'] == 'image/png':