1"""INT values from :rfc:`5545`."""
2
3from typing import Any, ClassVar
4
5from icalendar.compatibility import Self
6from icalendar.error import JCalParsingError
7from icalendar.parser import Parameters
8from icalendar.parser_tools import ICAL_TYPE
9
10
11class vInt(int):
12 """Integer
13
14 Value Name:
15 INTEGER
16
17 Purpose:
18 This value type is used to identify properties that contain a
19 signed integer value.
20
21 Format Definition:
22 This value type is defined by the following notation:
23
24 .. code-block:: text
25
26 integer = (["+"] / "-") 1*DIGIT
27
28 Description:
29 If the property permits, multiple "integer" values are
30 specified by a COMMA-separated list of values. The valid range
31 for "integer" is -2147483648 to 2147483647. If the sign is not
32 specified, then the value is assumed to be positive.
33
34 The ``__new__`` method creates a vInt instance:
35
36 Parameters:
37 value: Integer value to encode. Must be within :attr:`min` to :attr:`max`.
38 params: Optional parameter dictionary for the property.
39
40 Returns:
41 vInt instance
42
43 Raises:
44 ValueError: If the value is outside the RFC 5545 signed 32-bit integer range
45 as defined in :attr:`min` and :attr:`max`.
46
47 Examples:
48
49 .. code-block:: text
50
51 1234567890
52 -1234567890
53 +1234567890
54 432109876
55
56 .. code-block:: pycon
57
58 >>> from icalendar.prop import vInt
59 >>> integer = vInt.from_ical('1234567890')
60 >>> integer
61 1234567890
62 >>> integer = vInt.from_ical('-1234567890')
63 >>> integer
64 -1234567890
65 >>> integer = vInt.from_ical('+1234567890')
66 >>> integer
67 1234567890
68 >>> integer = vInt.from_ical('432109876')
69 >>> integer
70 432109876
71
72 Create a PRIORITY property (1 = highest priority):
73
74 .. code-block:: pycon
75
76 >>> priority = vInt(1)
77 >>> priority
78 1
79 >>> priority.to_ical()
80 b'1'
81
82 Create SEQUENCE property (for versioning):
83
84 .. code-block:: pycon
85
86 >>> sequence = vInt(3)
87 >>> sequence.to_ical()
88 b'3'
89 """
90
91 default_value: ClassVar[str] = "INTEGER"
92 params: Parameters
93
94 min: ClassVar[int] = -2_147_483_648
95 """min: The minimum valid value per :rfc:`5545#section-3.3.8` (``-2147483648``)."""
96 max: ClassVar[int] = 2_147_483_647
97 """max: The maximum valid value per :rfc:`5545#section-3.3.8` (``2147483647``)."""
98
99 def __new__(cls, *args, params: dict[str, Any] | None = None, **kwargs):
100 self = super().__new__(cls, *args, **kwargs)
101 self.params = Parameters(params)
102 if not (cls.min <= self <= cls.max):
103 raise ValueError(
104 f"Integer {self} is outside the RFC 5545 range [{cls.min}, {cls.max}]"
105 )
106 return self
107
108 def to_ical(self) -> bytes:
109 return str(self).encode("utf-8")
110
111 @property
112 def ical_value(self) -> int:
113 """INTEGER property type according to :rfc:`5545#section-3.3.8`"""
114 return int(self)
115
116 @classmethod
117 def from_ical(cls, ical: ICAL_TYPE):
118 try:
119 value = int(ical)
120 except Exception as e:
121 raise ValueError(f"Expected int, got: {ical}") from e
122 return cls(value)
123
124 @classmethod
125 def examples(cls) -> list[Self]:
126 """Examples of vInt."""
127 return [vInt(1000), vInt(-42)]
128
129 from icalendar.param import VALUE
130
131 def to_jcal(self, name: str) -> list:
132 """The jCal representation of this property according to :rfc:`7265`."""
133 return [name, self.params.to_jcal(), self.VALUE.lower(), int(self)]
134
135 @classmethod
136 def from_jcal(cls, jcal_property: list) -> Self:
137 """Parse jCal from :rfc:`7265`.
138
139 Parameters:
140 jcal_property: The jCal property to parse.
141
142 Raises:
143 ~error.JCalParsingError: If the provided jCal is invalid.
144 """
145 JCalParsingError.validate_property(jcal_property, cls)
146 JCalParsingError.validate_value_type(jcal_property[3], int, cls, 3)
147 return cls(
148 jcal_property[3],
149 params=Parameters.from_jcal_property(jcal_property),
150 )
151
152 @classmethod
153 def parse_jcal_value(cls, value: Any) -> int:
154 """Parse a jCal value for vInt.
155
156 Raises:
157 ~error.JCalParsingError: If the value is not an int.
158 """
159 JCalParsingError.validate_value_type(value, int, cls)
160 return cls(value)
161
162
163__all__ = ["vInt"]