Coverage for jutil/parse.py: 77%
51 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-10-07 16:40 -0500
« prev ^ index » next coverage.py v6.5.0, created at 2022-10-07 16:40 -0500
1import logging
2from datetime import datetime, time, date
3from typing import Optional, Any
4from django.core.exceptions import ValidationError
5from django.utils.translation import gettext as _
6import pytz
7from django.utils.dateparse import parse_datetime as django_parse_datetime
8from django.utils.dateparse import parse_date as django_parse_date
10logger = logging.getLogger(__name__)
12TRUE_VALUES = (
13 "true",
14 "1",
15 "yes",
16 "on",
17 "enabled",
18)
20FALSE_VALUES = (
21 "false",
22 "0",
23 "no",
24 "off",
25 "disabled",
26 "none",
27 "null",
28)
31def parse_bool(v: str) -> bool:
32 """
33 Parses boolean value
34 :param v: Input string
35 :return: bool
36 """
37 s = str(v).lower()
38 if s in TRUE_VALUES:
39 return True
40 if s in FALSE_VALUES:
41 return False
42 raise ValidationError(_("%(value)s is not one of the available choices") % {"value": v})
45def parse_datetime(v: str, tz: Any = None) -> datetime:
46 """
47 Parses ISO date/datetime string to timezone-aware datetime.
48 Supports YYYY-MM-DD date strings where time part is missing.
49 Returns always timezone-aware datetime (assumes UTC if timezone missing).
50 :param v: Input string to parse
51 :param tz: Default pytz timezone or if None then use UTC as default
52 :return: datetime with timezone
53 """
54 try:
55 t = django_parse_datetime(v)
56 if t is None:
57 t_date: Optional[date] = django_parse_date(v)
58 if t_date is None: 58 ↛ 60line 58 didn't jump to line 60, because the condition on line 58 was never false
59 raise ValidationError(_("“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] format.") % {"value": v})
60 t = datetime.combine(t_date, time())
61 if tz is None: 61 ↛ 63line 61 didn't jump to line 63, because the condition on line 61 was never false
62 tz = pytz.utc
63 return t if t.tzinfo else tz.localize(t)
64 except Exception as err:
65 raise ValidationError(_("“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] format.") % {"value": v}) from err
68def parse_bool_or_none(v: str) -> Optional[bool]:
69 """
70 Parses boolean value, or returns None if parsing fails.
71 :param v: Input string
72 :return: bool or None
73 """
74 s = str(v).lower()
75 if s in TRUE_VALUES:
76 return True
77 if s in FALSE_VALUES:
78 return False
79 return None
82def parse_datetime_or_none(v: str, tz: Any = None) -> Optional[datetime]:
83 """
84 Parses ISO date/datetime string to timezone-aware datetime.
85 Supports YYYY-MM-DD date strings where time part is missing.
86 Returns timezone-aware datetime (assumes UTC if timezone missing) or None if parsing fails.
87 :param v: Input string to parse
88 :param tz: Default pytz timezone or if None then use UTC as default
89 :return: datetime with timezone or None
90 """
91 try:
92 t = django_parse_datetime(v)
93 if t is None:
94 t_date: Optional[date] = django_parse_date(v)
95 if t_date is None: 95 ↛ 97line 95 didn't jump to line 97, because the condition on line 95 was never false
96 return None
97 t = datetime.combine(t_date, time())
98 if tz is None: 98 ↛ 100line 98 didn't jump to line 100, because the condition on line 98 was never false
99 tz = pytz.utc
100 return t if t.tzinfo else tz.localize(t)
101 except Exception:
102 return None