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