From 3d2b1dff4b13dc880f56b49c6541faa85b5cb752 Mon Sep 17 00:00:00 2001 From: Gwendolyn Date: Fri, 18 Apr 2025 00:29:17 +0200 Subject: [PATCH] import shapely shapes and NDArray only for type checking --- docker/build.sh | 4 +- .../mapdata/utils/cache/accessrestrictions.py | 16 ++++---- src/c3nav/mapdata/utils/cache/indexed.py | 38 ++++++++++--------- 3 files changed, 31 insertions(+), 27 deletions(-) diff --git a/docker/build.sh b/docker/build.sh index eca474f4..3692962c 100755 --- a/docker/build.sh +++ b/docker/build.sh @@ -12,7 +12,7 @@ if [[ "$1" == "git" ]]; then CONTEXT="https://github.com/c3nav/c3nav.git#${COMMIT}" fi -docker buildx build -f docker/Dockerfile \ +podman buildx build -f docker/Dockerfile \ --platform linux/arm64,linux/amd64 \ --build-arg "COMMIT=${COMMIT}" \ --label "org.opencontainers.image.version=${COMMIT}" \ @@ -25,7 +25,7 @@ docker buildx build -f docker/Dockerfile \ --cache-to "type=registry,ref=ghcr.io/c3nav/c3nav_cache:main,mode=max" \ --push "${CONTEXT}" -docker buildx build -f docker/tileserver.dockerfile \ +podman buildx build -f docker/tileserver.dockerfile \ --platform linux/arm64,linux/amd64 \ --build-arg "COMMIT=${COMMIT}" \ --label "org.opencontainers.image.version=${COMMIT}" \ diff --git a/src/c3nav/mapdata/utils/cache/accessrestrictions.py b/src/c3nav/mapdata/utils/cache/accessrestrictions.py index b9efca2a..7f6b6333 100644 --- a/src/c3nav/mapdata/utils/cache/accessrestrictions.py +++ b/src/c3nav/mapdata/utils/cache/accessrestrictions.py @@ -2,11 +2,13 @@ import operator import struct from functools import reduce from os import PathLike -from typing import Self, Iterator +from typing import Self, Iterator, Union, TYPE_CHECKING import numpy as np -from numpy.typing import NDArray -from shapely import Polygon, MultiPolygon + +if TYPE_CHECKING: + from numpy.typing import NDArray + from shapely import Polygon, MultiPolygon from c3nav.mapdata.utils.cache.indexed import LevelGeometryIndexed @@ -59,7 +61,7 @@ class AccessRestrictionAffected(LevelGeometryIndexed): self.restrictions.append(restriction) return i - def __getitem__(self, selector: tuple[slice, slice] | Polygon | MultiPolygon) -> "AccessRestrictionAffectedCells": + def __getitem__(self, selector: Union[tuple[slice, slice], 'Polygon', 'MultiPolygon']) -> "AccessRestrictionAffectedCells": return AccessRestrictionAffectedCells(self, selector) def __setitem__(self, selector, value): @@ -68,15 +70,15 @@ class AccessRestrictionAffected(LevelGeometryIndexed): class AccessRestrictionAffectedCells: def __init__(self, parent: AccessRestrictionAffected, - selector: tuple[slice, slice] | Polygon | MultiPolygon): + selector: Union[tuple[slice, slice], 'Polygon','MultiPolygon']): self.parent = parent self.selector = selector self.values = self._get_values() - def _get_values(self) -> NDArray: + def _get_values(self) -> 'NDArray': return LevelGeometryIndexed.__getitem__(self.parent, self.selector) - def _set(self, values: NDArray): + def _set(self, values: 'NDArray'): self.values = values LevelGeometryIndexed.__setitem__(self.parent, self.selector, values) diff --git a/src/c3nav/mapdata/utils/cache/indexed.py b/src/c3nav/mapdata/utils/cache/indexed.py index f2425685..dd1270e6 100644 --- a/src/c3nav/mapdata/utils/cache/indexed.py +++ b/src/c3nav/mapdata/utils/cache/indexed.py @@ -2,10 +2,11 @@ import math import struct from os import PathLike from pathlib import Path -from typing import Self, Optional +from typing import Self, Optional, Union, TYPE_CHECKING -from numpy.typing import NDArray -from shapely import Polygon, MultiPolygon +if TYPE_CHECKING: + from numpy.typing import NDArray + from shapely import Polygon, MultiPolygon import numpy as np @@ -29,18 +30,18 @@ class GeometryIndexed: variant_id = 0 def __init__(self, resolution: Optional[int] = None, x: int = 0, y: int = 0, - data: NDArray = None, filename: str | bytes | PathLike = None): + data: 'NDArray' = None, filename: str | bytes | PathLike = None): if resolution is None: from django.conf import settings resolution = settings.CACHE_RESOLUTION self.resolution: int = resolution self.x = x self.y = y - self.data: NDArray = data if data is not None else self._get_empty_array() + self.data: 'NDArray' = data if data is not None else self._get_empty_array() self.filename = filename @classmethod - def _get_empty_array(cls) -> NDArray: + def _get_empty_array(cls) -> 'NDArray': return np.empty((0, 0), dtype=cls.dtype) @classmethod @@ -64,7 +65,8 @@ class GeometryIndexed: cls._read_metadata(f, kwargs) # noinspection PyTypeChecker - kwargs['data'] = np.fromstring(f.read(width*height*cls.dtype().itemsize), cls.dtype).reshape((height, width)) + kwargs['data'] = np.fromstring(f.read(width * height * cls.dtype().itemsize), cls.dtype).reshape( + (height, width)) return cls(**kwargs) @classmethod @@ -88,7 +90,7 @@ class GeometryIndexed: def _write_metadata(self, f): pass - def get_geometry_bounds(self, geometry: Polygon | MultiPolygon) -> tuple[int, int, int, int]: + def get_geometry_bounds(self, geometry: Union['Polygon', 'MultiPolygon']) -> tuple[int, int, int, int]: minx, miny, maxx, maxy = geometry.bounds return ( int(math.floor(minx / self.resolution)), @@ -117,8 +119,8 @@ class GeometryIndexed: self.x = minx self.y = miny - def get_geometry_cells(self, geometry: Polygon | MultiPolygon, - bounds: Optional[tuple[int, int, int, int]] = None) -> NDArray: + def get_geometry_cells(self, geometry: Union['Polygon','MultiPolygon'], + bounds: Optional[tuple[int, int, int, int]] = None) -> 'NDArray': if bounds is None: bounds = self.get_geometry_bounds(geometry) minx, miny, maxx, maxy = bounds @@ -145,9 +147,9 @@ class GeometryIndexed: @property def bounds(self) -> tuple[int, int, int, int]: height, width = self.data.shape - return self.x, self.y, self.x+width, self.y+height + return self.x, self.y, self.x + width, self.y + height - def __getitem__(self, key: tuple[slice, slice] | Polygon | MultiPolygon) -> int: + def __getitem__(self, key: Union[tuple[slice, slice], 'Polygon','MultiPolygon']) -> int: if isinstance(key, tuple): xx, yy = key @@ -171,7 +173,7 @@ class GeometryIndexed: raise TypeError('GeometryIndexed index must be a shapely geometry or tuple, not %s' % type(key).__name__) - def __setitem__(self, key: Polygon | MultiPolygon, value: NDArray | int): + def __setitem__(self, key: Union['Polygon','MultiPolygon'], value: 'NDArray' | int): from shapely.geometry.base import BaseGeometry if isinstance(key, BaseGeometry): bounds = self.get_geometry_bounds(key) @@ -187,16 +189,16 @@ class GeometryIndexed: (minx, miny), (maxx, maxy) = Source.max_bounds() height, width = self.data.shape - image_data = np.zeros((int(math.ceil((maxy-miny)/self.resolution)), - int(math.ceil((maxx-minx)/self.resolution))), dtype=np.uint8) + image_data = np.zeros((int(math.ceil((maxy - miny) / self.resolution)), + int(math.ceil((maxx - minx) / self.resolution))), dtype=np.uint8) if self.data.size: # noinspection PyArgumentList minval = min(self.data.min(), 0) # noinspection PyArgumentList - maxval = max(self.data.max(), minval+0.01) - visible_data = ((self.data.astype(float)-minval)*255/(maxval-minval)).clip(0, 255).astype(np.uint8) - image_data[self.y:self.y+height, self.x:self.x+width] = visible_data + maxval = max(self.data.max(), minval + 0.01) + visible_data = ((self.data.astype(float) - minval) * 255 / (maxval - minval)).clip(0, 255).astype(np.uint8) + image_data[self.y:self.y + height, self.x:self.x + width] = visible_data from PIL import Image return Image.fromarray(np.flip(image_data, axis=0), 'L')