1"""BOOLEAN values from :rfc:`5545`."""
2
3from typing import Any, ClassVar
4
5from icalendar.caselessdict import CaselessDict
6from icalendar.compatibility import Self
7from icalendar.error import JCalParsingError
8from icalendar.parser import Parameters
9
10
11class vBoolean(int):
12 """An iCalendar boolean value.
13
14 Converts between iCalendar ``BOOLEAN`` value types and Python boolean values.
15 In iCalendar data, boolean values are represented as "TRUE" or "FALSE". Values
16 parsed from iCalendar text are case insensitive. ``True``, ``true``, and ``TRUE``
17 are all accepted when converting from iCalendar to Python.
18
19 Conforming with :rfc:`5545#section-3.3.2`, boolean values are represented in
20 iCalendar data as either ``TRUE`` or ``FALSE``.
21
22 Example:
23 Parse and create iCalendar boolean values.
24
25 .. code-block:: pycon
26
27 >>> from icalendar.prop import vBoolean
28 >>> boolean = vBoolean.from_ical('TRUE')
29 >>> boolean
30 True
31
32 >>> boolean = vBoolean.from_ical('fAlse')
33 >>> boolean
34 False
35
36 >>> vBoolean(True).to_ical()
37 b'TRUE'
38 """
39
40 default_value: ClassVar[str] = "BOOLEAN"
41 params: Parameters
42
43 BOOL_MAP = CaselessDict({"true": True, "false": False})
44
45 def __new__(
46 cls, *args: Any, params: dict[str, Any] | None = None, **kwargs: Any
47 ) -> Self:
48 self = super().__new__(cls, *args, **kwargs)
49 self.params = Parameters(params)
50 return self
51
52 def to_ical(self) -> bytes:
53 """Converts a :class:`~icalendar.prop.boolean.vBoolean` to a BOOLEAN property type.
54
55 This class method takes a ``vBoolean``—a Python boolean value—and converts it to an iCalendar BOOLEAN property type, in compliance with :rfc:`5545#section-3.3.2`.
56
57 Returns:
58 Either "TRUE" or "FALSE" as bytes, depending on the value of the ``vBoolean``.
59 """
60 return b"TRUE" if self else b"FALSE"
61
62 @property
63 def ical_value(self) -> bool:
64 """BOOLEAN property type according to :rfc:`5545#section-3.3.2`"""
65 return bool(self)
66
67 @classmethod
68 def from_ical(cls, ical: str) -> bool:
69 try:
70 return cls.BOOL_MAP[ical]
71 except Exception as e:
72 raise ValueError(f"Expected 'TRUE' or 'FALSE'. Got {ical}") from e
73
74 @classmethod
75 def examples(cls) -> list[Self]:
76 """Examples of vBoolean."""
77 return [
78 cls(True),
79 cls(False),
80 ]
81
82 from icalendar.param import VALUE
83
84 def to_jcal(self, name: str) -> list:
85 """The jCal representation of this property according to :rfc:`7265`."""
86 return [name, self.params.to_jcal(), self.VALUE.lower(), bool(self)]
87
88 @classmethod
89 def from_jcal(cls, jcal_property: list) -> Self:
90 """Parse jCal from :rfc:`7265` to a vBoolean.
91
92 Parameters:
93 jcal_property: The jCal property to parse.
94
95 Raises:
96 ~error.JCalParsingError: If the provided jCal is invalid.
97 """
98 JCalParsingError.validate_property(jcal_property, cls)
99 JCalParsingError.validate_value_type(jcal_property[3], bool, cls, 3)
100 return cls(
101 jcal_property[3],
102 params=Parameters.from_jcal_property(jcal_property),
103 )
104
105
106__all__ = ["vBoolean"]