Skip to content

Commit

Permalink
first datex2 approach
Browse files Browse the repository at this point in the history
  • Loading branch information
the-infinity committed Nov 10, 2023
1 parent 3479208 commit ecf37d1
Show file tree
Hide file tree
Showing 8 changed files with 732 additions and 0 deletions.
2 changes: 2 additions & 0 deletions dev/api_tests/public_api/datex2.http
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
### List datex2 parking sites
GET {{api_host}}/api/public/datex2/json
31 changes: 31 additions & 0 deletions webapp/common/dataclass.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""
Copyright 2023 binary butterfly GmbH
Use of this source code is governed by an MIT-style license that can be found in the LICENSE.txt.
"""

from dataclasses import is_dataclass, asdict
from typing import Any

from validataclass.helpers import UnsetValue


def recursive_to_dict(data: Any):

Check failure on line 12 in webapp/common/dataclass.py

View workflow job for this annotation

GitHub Actions / lint (3)

Ruff (I001)

webapp/common/dataclass.py:6:1: I001 Import block is un-sorted or un-formatted

Check failure on line 12 in webapp/common/dataclass.py

View workflow job for this annotation

GitHub Actions / lint (3)

Ruff (I001)

webapp/common/dataclass.py:6:1: I001 Import block is un-sorted or un-formatted
if is_dataclass(data):
return {key: recursive_to_dict(value) for key, value in asdict(data).items()}
if isinstance(data, list):
return [recursive_to_dict(item) for item in data]
return data


def filter_unset_value(data: Any) -> Any:
if isinstance(data, dict):
return {key: filter_unset_value(value) for key, value in data.items() if value is not UnsetValue}
if isinstance(data, list):
return [filter_unset_value(item) for item in data if item is not UnsetValue]
return data


class DataclassMixin:

def to_dict(self):
return filter_unset_value(recursive_to_dict(self))
35 changes: 35 additions & 0 deletions webapp/public_rest_api/datex2/datex2_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""
Copyright 2023 binary butterfly GmbH
Use of this source code is governed by an MIT-style license that can be found in the LICENSE.txt.
"""

from webapp.public_rest_api.datex2.datex2_mapper import Datex2Mapper
from webapp.public_rest_api.datex2.datex2_models import Datex2Publication
from webapp.repositories import SourceRepository
from webapp.shared.parking_site import GenericParkingSiteHandler
from webapp.shared.parking_site.parking_site_search_query import ParkingSiteSearchInput


class Datex2Handler(GenericParkingSiteHandler):
source_repository: SourceRepository
datex2_mapper: Datex2Mapper = Datex2Mapper()

def __init__(self, *args, source_repository: SourceRepository, **kwargs):
super().__init__(*args, **kwargs)
self.source_repository = source_repository

def get_parking_sites(self, search_query: ParkingSiteSearchInput) -> Datex2Publication:
parking_sites = self.get_parking_site_list(search_query)

if search_query.source_uid is None:
name = 'Aggregated parking sites'
else:
source = self.source_repository.fetch_source_by_uid(search_query.source_uid)
name = source.name

datex_2_publication = self.datex2_mapper.map_parking_sites(
parking_sites=parking_sites,
name=name,
)

return datex_2_publication

Check failure on line 35 in webapp/public_rest_api/datex2/datex2_handler.py

View workflow job for this annotation

GitHub Actions / lint (3)

Ruff (RET504)

webapp/public_rest_api/datex2/datex2_handler.py:35:16: RET504 Unnecessary assignment to `datex_2_publication` before `return` statement

Check failure on line 35 in webapp/public_rest_api/datex2/datex2_handler.py

View workflow job for this annotation

GitHub Actions / lint (3)

Ruff (RET504)

webapp/public_rest_api/datex2/datex2_handler.py:35:16: RET504 Unnecessary assignment to `datex_2_publication` before `return` statement
70 changes: 70 additions & 0 deletions webapp/public_rest_api/datex2/datex2_mapper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
"""
Copyright 2023 binary butterfly GmbH
Use of this source code is governed by an MIT-style license that can be found in the LICENSE.txt.
"""

from webapp.models import ParkingSite
from webapp.models.parking_site import OpeningStatus, ParkingSiteType
from webapp.public_rest_api.datex2.datex2_models import Datex2ParkingSite, Datex2LocationAndDimension, Datex2Coordinate, \
Datex2ParkingSiteType, Datex2Publication, Datex2ParkingPublicationLight


class Datex2Mapper:

Check failure on line 12 in webapp/public_rest_api/datex2/datex2_mapper.py

View workflow job for this annotation

GitHub Actions / lint (3)

Ruff (I001)

webapp/public_rest_api/datex2/datex2_mapper.py:6:1: I001 Import block is un-sorted or un-formatted

Check failure on line 12 in webapp/public_rest_api/datex2/datex2_mapper.py

View workflow job for this annotation

GitHub Actions / lint (3)

Ruff (I001)

webapp/public_rest_api/datex2/datex2_mapper.py:6:1: I001 Import block is un-sorted or un-formatted

def map_parking_sites(self, name: str, parking_sites: list[ParkingSite]) -> Datex2Publication:
publication = Datex2Publication(
parkingPublicationLight=Datex2ParkingPublicationLight(
name=name,
parkingSite=[self.map_parking_site(parking_site) for parking_site in parking_sites],
),
)

return publication

Check failure on line 22 in webapp/public_rest_api/datex2/datex2_mapper.py

View workflow job for this annotation

GitHub Actions / lint (3)

Ruff (RET504)

webapp/public_rest_api/datex2/datex2_mapper.py:22:16: RET504 Unnecessary assignment to `publication` before `return` statement

Check failure on line 22 in webapp/public_rest_api/datex2/datex2_mapper.py

View workflow job for this annotation

GitHub Actions / lint (3)

Ruff (RET504)

webapp/public_rest_api/datex2/datex2_mapper.py:22:16: RET504 Unnecessary assignment to `publication` before `return` statement

def map_parking_site(self, parking_site: ParkingSite) -> Datex2ParkingSite:
datex2_parking_site = Datex2ParkingSite(
uid=str(parking_site.id),
type=self.map_parking_site_type(parking_site.type),
locationAndDimension=Datex2LocationAndDimension(
coordinatesForDisplay=Datex2Coordinate(
latitude=float(parking_site.lat),
longitude=float(parking_site.lon),
),
),
)

if parking_site.has_realtime_data:
if parking_site.realtime_capacity is not None:
datex2_parking_site.availableSpaces = parking_site.realtime_capacity

if parking_site.realtime_opening_status == OpeningStatus.OPEN:
datex2_parking_site.isOpenNow = True
elif parking_site.realtime_opening_status == OpeningStatus.CLOSED:
datex2_parking_site.isOpenNow = False

field_mapping = {
'description': 'description',
'modified': 'lastUpdate',
'max_stay': 'maximumParkingDuration',
'name': 'name',
'capacity': 'numberOfSpaces',
'fee_description': 'tariffDescription',
'public_url': 'urlLinkAddress',
}

for source, target in field_mapping.items():
if getattr(parking_site, source, None) is None:
continue
setattr(datex2_parking_site, target, getattr(parking_site, source))

return datex2_parking_site

@staticmethod
def map_parking_site_type(parking_site_type: ParkingSiteType) -> Datex2ParkingSiteType:
return {
ParkingSiteType.CAR_PARK: Datex2ParkingSiteType.carPark,
ParkingSiteType.ON_STREET: Datex2ParkingSiteType.onStreet,
ParkingSiteType.UNDERGROUND: Datex2ParkingSiteType.carPark,
ParkingSiteType.OFF_STREET_PARKING_GROUND: Datex2ParkingSiteType.offStreetParkingGround,

}.get(parking_site_type, Datex2ParkingSiteType.other)
Loading

0 comments on commit ecf37d1

Please sign in to comment.