1"""FREQ value type of RECUR from :rfc:`5545`."""
2
3from typing import Any
4
5from icalendar.caselessdict import CaselessDict
6from icalendar.compatibility import Self
7from icalendar.error import JCalParsingError
8from icalendar.parser import Parameters
9from icalendar.parser_tools import DEFAULT_ENCODING, to_unicode
10
11
12class vFrequency(str):
13 """A simple class that catches illegal values."""
14
15 params: Parameters
16 __slots__ = ("params",)
17
18 frequencies = CaselessDict(
19 {
20 "SECONDLY": "SECONDLY",
21 "MINUTELY": "MINUTELY",
22 "HOURLY": "HOURLY",
23 "DAILY": "DAILY",
24 "WEEKLY": "WEEKLY",
25 "MONTHLY": "MONTHLY",
26 "YEARLY": "YEARLY",
27 }
28 )
29
30 def __new__(
31 cls,
32 value,
33 encoding=DEFAULT_ENCODING,
34 /,
35 params: dict[str, Any] | None = None,
36 ):
37 value = to_unicode(value, encoding=encoding)
38 self = super().__new__(cls, value)
39 if self not in vFrequency.frequencies:
40 raise ValueError(f"Expected frequency, got: {self}")
41 self.params = Parameters(params)
42 return self
43
44 def to_ical(self):
45 return self.encode(DEFAULT_ENCODING).upper()
46
47 @classmethod
48 def from_ical(cls, ical):
49 try:
50 return cls(ical.upper())
51 except Exception as e:
52 raise ValueError(f"Expected frequency, got: {ical}") from e
53
54 @classmethod
55 def parse_jcal_value(cls, value: Any) -> Self:
56 """Parse a jCal value for vFrequency.
57
58 Raises:
59 ~error.JCalParsingError: If the value is not a valid frequency.
60 """
61 JCalParsingError.validate_value_type(value, str, cls)
62 try:
63 return cls(value)
64 except ValueError as e:
65 raise JCalParsingError(
66 "The value must be a valid frequency.", cls, value=value
67 ) from e
68
69
70__all__ = ["vFrequency"]