76 lines
2.9 KiB
Python
76 lines
2.9 KiB
Python
import datetime
|
|
import logging
|
|
import os
|
|
import typing
|
|
from decimal import Decimal
|
|
|
|
from django.http import HttpResponse
|
|
from django.utils import formats, timezone
|
|
from rest_framework.exceptions import APIException
|
|
|
|
_log = logging.getLogger(__name__)
|
|
|
|
|
|
def catch_exception(func):
|
|
"""
|
|
Catches any exceptions raised in the function.
|
|
If the exception is a subclass of APIException, reraise it to be handled by DRF.
|
|
If not a subclass of APIException, then raise an APIException so that DRF handles it anyway and shows human error
|
|
"""
|
|
|
|
def wrapper(*args, **kwargs):
|
|
try:
|
|
return func(*args, **kwargs)
|
|
except APIException as e:
|
|
raise e
|
|
except Exception as e:
|
|
_log.error(f'Error: {str(e)}')
|
|
raise APIException(detail={
|
|
'status': 'error',
|
|
'code': 'unknown',
|
|
'detail': f'{str(e)}'
|
|
})
|
|
|
|
return wrapper
|
|
|
|
|
|
def dtnow(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0,
|
|
tz: timezone = timezone.utc, local=False) -> datetime.datetime:
|
|
""" returns current datetime or datetime in future/past by time units
|
|
use positive/negative time units for future/past datetime
|
|
:param tz: timezone or None to use datetime without timezone, can not be None if local parameter is True
|
|
:param local: True to change returning value timezone to user local
|
|
:return: datetime.datetime object
|
|
"""
|
|
if not tz: # make sure None is used for disabling and only for nonlocal dates
|
|
tz = timezone.utc if local else None
|
|
ret = datetime.datetime.now(tz=tz) + datetime.timedelta(days=days, seconds=seconds, microseconds=microseconds,
|
|
milliseconds=milliseconds, minutes=minutes, hours=hours,
|
|
weeks=weeks)
|
|
return timezone.localtime(ret) if local else ret
|
|
|
|
|
|
def fmt_input(
|
|
val: typing.Union[str, bool, int, float, Decimal, datetime.datetime, datetime.date, datetime.time],
|
|
format: str = None) -> str:
|
|
""" Make localized string for specified input value using specified format
|
|
:param val: value to format, may be of different types
|
|
:param format: format for data or None to use default localized format
|
|
:return: localized data as str
|
|
"""
|
|
return formats.localize_input(val, format)
|
|
|
|
|
|
def store_file_response(file_name):
|
|
with open(file_name, 'rb') as fh:
|
|
return httpFileResponse(fh.read(), os.path.basename(file_name))
|
|
|
|
|
|
def httpFileResponse(content, fname='file', zip=None):
|
|
response = HttpResponse(content, content_type="application/file")
|
|
fname = fname.replace('"', '').replace("'", '')
|
|
if zip:
|
|
response['Content-Disposition'] = f'attachment; filename="{fname}.zip"'
|
|
else:
|
|
response['Content-Disposition'] = f'attachment; filename="{fname}"'
|
|
return response
|