-
Ernesto Rico Schmidt authored
- Add type annotations, - Cleanup logic, - utils.parse_time now accepts to time format strings.
Ernesto Rico Schmidt authored- Add type annotations, - Cleanup logic, - utils.parse_time now accepts to time format strings.
utils.py 5.10 KiB
#
# steering, Programme/schedule management for AURA
#
# Copyright (C) 2011-2017, 2020, Ernesto Rico Schmidt
# Copyright (C) 2017-2019, Ingo Leindecker
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import json
import typing
from datetime import date, datetime, time
from typing import Dict, Optional, Tuple, Union
import requests
from rest_framework import exceptions
from django.utils import timezone
from steering.settings import CBA_AJAX_URL, CBA_API_KEY, DEBUG
if typing.TYPE_CHECKING:
from program.models import Host, Note, Show
def parse_datetime(date_string: str) -> datetime:
"""
parse a datetime string and return a timezone aware datetime object
"""
try:
parsed_datetime = datetime.strptime(date_string, "%Y-%m-%d %H:%M:%S")
except ValueError:
parsed_datetime = datetime.strptime(date_string, "%Y-%m-%d %H:%M:%S%z")
return (
timezone.make_aware(parsed_datetime)
if timezone.is_naive(parsed_datetime)
else parsed_datetime
)
def parse_date(date_string: str) -> date:
"""
parse a date string and return a date object
"""
return datetime.strptime(date_string, "%Y-%m-%d").date()
def parse_time(date_string: str) -> time:
"""
parse a time string and return a time object
"""
if len(date_string) == 5:
return datetime.strptime(date_string, "%H:%M").time()
else:
return datetime.strptime(date_string, "%H:%M:%S").time()
def get_audio_url(cba_id: Optional[int]) -> str:
"""
Retrieve the direct URL to the mp3 in CBA
In order to retrieve the URL, stations need
- to be whitelisted by CBA
- an API Key
For these contact cba@fro.at
"""
if not cba_id or CBA_API_KEY == "":
return ""
else:
if DEBUG:
url = (
"https://cba.fro.at/wp-content/plugins/cba/ajax/cba-get-filename.php?post_id="
+ str(cba_id)
+ "&c=Ml3fASkfwR8"
)
else:
url = (
CBA_AJAX_URL
+ "?action=cba_ajax_get_filename&post_id="
+ str(cba_id)
+ "&api_key="
+ CBA_API_KEY
)
try:
return requests.get(url).json()
except (requests.RequestException, json.JSONDecodeError):
# TODO: we might want to add some logging
return ""
def get_values(
kwargs: Dict[str, str], *keys: str
) -> Union[Tuple[Union[int, str, None], ...], int, str, None]:
"""Get the values of the keys from the kwargs."""
def int_if_digit(value: Optional[str]) -> Optional[Union[int, str]]:
return int(value) if value and value.isdigit() else value
values = [kwargs.get(key) for key in keys]
if len(values) > 1:
return tuple(int_if_digit(value) for value in values)
else:
return int_if_digit(values[0])
def delete_links(instance: Union["Host", "Note", "Show"]) -> Union["Host", "Note", "Show"]:
"""Delete the links associated with the instance."""
if instance.links.count() > 0:
for link in instance.links.all():
link.delete(keep_parents=True)
return instance
class DisabledObjectPermissionCheckMixin:
"""
At the time of writing permission checks were entirely circumvented by manual
queries in viewsets. To make code refactoring easier and allow
the paced introduction of .get_object() in viewsets, object permission checks
need to be disabled until permission checks have been refactored as well.
Object permissions checks should become mandatory once proper permission_classes
are assigned to viewsets. This mixin should be removed afterwards.
"""
# The text above becomes the viewset’s doc string otherwise and is displayed in
# the generated OpenAPI schema.
__doc__ = None
def check_object_permissions(self, request, obj):
pass
class NestedObjectFinderMixin:
ROUTE_FILTER_LOOKUPS = {}
def _get_route_filters(self) -> Dict[str, int]:
filter_kwargs = {}
for key, value in self.kwargs.items():
if key in self.ROUTE_FILTER_LOOKUPS:
try:
filter_kwargs[self.ROUTE_FILTER_LOOKUPS[key]] = int(value)
except ValueError:
raise exceptions.ValidationError(
detail=f"{key} must map to an integer value.", code="invalid-pk"
)
return filter_kwargs
def get_queryset(self):
return super().get_queryset().filter(**self._get_route_filters())