Source code for gis.models.coordinates

from onegov.core.custom import json


from typing import overload, Any, Literal, TYPE_CHECKING
if TYPE_CHECKING:
    from sqlalchemy.schema import Column
    from typing import TypeAlias


[docs] class Coordinates(json.Serializable, keys=('lon', 'lat', 'zoom')): """ Represents a pair of coordinates. May contain zoom factor and other information like marker icon and color. Note that only latitude and longitude really matter, the rest may or may not be used. """
[docs] __slots__ = ('lon', 'lat', 'zoom')
[docs] lat: float | None
[docs] lon: float | None
[docs] zoom: int | None
if TYPE_CHECKING: @overload def __new__( cls, lat: float, lon: float, zoom: int | None = None, ) -> 'RealCoordinates': ... @overload def __new__( cls, lat: None = None, lon: None = None, zoom: None = None, ) -> 'NullCoordinates': ... def __new__( cls, lat: float | None = None, lon: float | None = None, zoom: int | None = None, ) -> 'Coordinates': raise NotImplementedError() else: def __init__( self, lat: float | None = None, lon: float | None = None, zoom: int | None = None ) -> None: self.lat = lat self.lon = lon self.zoom = zoom
[docs] def __bool__(self) -> bool: if self.lat is None or self.lon is None: return False return True
[docs] def __eq__(self, other: object) -> bool: if not isinstance(other, Coordinates): return False return ( self.lat == other.lat and self.lon == other.lon and self.zoom == other.zoom )
if TYPE_CHECKING:
[docs] class NullCoordinates(Coordinates, keys=('lon', 'lat', 'zoom')):
[docs] lat: None
[docs] lon: None
[docs] zoom: None
[docs] def __bool__(self) -> Literal[False]: return False
class RealCoordinates(Coordinates, keys=('lon', 'lat', 'zoom')): lat: float lon: float zoom: int | None def __bool__(self) -> Literal[True]: return True AnyCoordinates: TypeAlias = RealCoordinates | NullCoordinates
[docs] class CoordinatesMixin: """ Extends any class that has a content dictionary field with a single coordinates pair. """ if TYPE_CHECKING: # forward declare content column from ContentMixin
[docs] content: Column[dict[str, Any]]
@property
[docs] def coordinates(self) -> 'AnyCoordinates': return self.content.get('coordinates') or Coordinates()
@coordinates.setter def coordinates(self, value: 'AnyCoordinates') -> None: self.content = self.content or {} self.content['coordinates'] = value or {}