Source code for icalendar.prop.integer

"""INT values from :rfc:`5545`."""

from typing import Any, ClassVar
from xml.etree.ElementTree import Element, SubElement

from icalendar.compatibility import Self
from icalendar.error import JCalParsingError, XCalParsingError
from icalendar.parser import Parameters
from icalendar.parser.xcal.adapter import ElementAdapter
from icalendar.parser.xcal.base import XCalParser
from icalendar.parser.xcal.wrapper import from_xcal_wrapper
from icalendar.parser_tools import ICAL_TYPE


[docs] class vInt(int): """Integer Value Name: INTEGER Purpose: This value type is used to identify properties that contain a signed integer value. Format Definition: This value type is defined by the following notation: .. code-block:: text integer = (["+"] / "-") 1*DIGIT Description: If the property permits, multiple "integer" values are specified by a COMMA-separated list of values. The valid range for "integer" is -2147483648 to 2147483647. If the sign is not specified, then the value is assumed to be positive. The ``__new__`` method creates a vInt instance: Parameters: value: Integer value to encode. Must be within :attr:`min` to :attr:`max`. params: Optional parameter dictionary for the property. Returns: vInt instance Raises: ValueError: If the value is outside the RFC 5545 signed 32-bit integer range as defined in :attr:`min` and :attr:`max`. Examples: .. code-block:: text 1234567890 -1234567890 +1234567890 432109876 .. code-block:: pycon >>> from icalendar.prop import vInt >>> integer = vInt.from_ical('1234567890') >>> integer 1234567890 >>> integer = vInt.from_ical('-1234567890') >>> integer -1234567890 >>> integer = vInt.from_ical('+1234567890') >>> integer 1234567890 >>> integer = vInt.from_ical('432109876') >>> integer 432109876 Create a PRIORITY property (1 = highest priority): .. code-block:: pycon >>> priority = vInt(1) >>> priority 1 >>> priority.to_ical() b'1' Create SEQUENCE property (for versioning): .. code-block:: pycon >>> sequence = vInt(3) >>> sequence.to_ical() b'3' """ default_value: ClassVar[str] = "INTEGER" params: Parameters min: ClassVar[int] = -2_147_483_648 """min: The minimum valid value per :rfc:`5545#section-3.3.8` (``-2147483648``).""" max: ClassVar[int] = 2_147_483_647 """max: The maximum valid value per :rfc:`5545#section-3.3.8` (``2147483647``).""" def __new__( cls, *args, params: dict[str, Any] | None = None, _validate_range: bool = True, **kwargs, ): self = super().__new__(cls, *args, **kwargs) self.params = Parameters(params) if not (cls.min <= self <= cls.max) and _validate_range: raise ValueError( f"Integer {self} is outside the RFC 5545 range [{cls.min}, {cls.max}]" ) return self
[docs] def to_ical(self) -> bytes: return str(self).encode("utf-8")
@property def ical_value(self) -> int: """INTEGER property type according to :rfc:`5545#section-3.3.8`""" return int(self)
[docs] @classmethod def from_ical(cls, ical: ICAL_TYPE): try: value = int(ical) except Exception as e: raise ValueError(f"Expected int, got: {ical}") from e return cls(value)
[docs] @classmethod def examples(cls) -> list[Self]: """Examples of vInt.""" return [cls(1000), cls(-42)]
from icalendar.param import VALUE
[docs] def to_jcal(self, name: str) -> list: """The jCal representation of this property according to :rfc:`7265`.""" return [name, self.params.to_jcal(), self.VALUE.lower(), int(self)]
[docs] @classmethod def from_jcal(cls, jcal_property: list) -> Self: """Parse jCal from :rfc:`7265`. Parameters: jcal_property: The jCal property to parse. Raises: ~icalendar.error.JCalParsingError: If the provided jCal is invalid. """ JCalParsingError.validate_property(jcal_property, cls) JCalParsingError.validate_value_type(jcal_property[3], int, cls, 3) return cls( jcal_property[3], params=Parameters.from_jcal_property(jcal_property), )
[docs] @classmethod def parse_jcal_value(cls, value: Any) -> int: """Parse a jCal value for vInt. Raises: ~icalendar.error.JCalParsingError: If the value is not an int. """ JCalParsingError.validate_value_type(value, int, cls) return cls(value)
[docs] @classmethod @from_xcal_wrapper def from_xcal(cls, parser: XCalParser, params: Parameters) -> Self: """Parse xCal from :rfc:`6321`. Parameters: element: The xCal element to parse. Raises: ~error.XCalParsingError: If the provided xCal is invalid. """ element = parser.parse_tag(cls.default_value) return cls.from_xcal_element(element, params)
XCAL_TYPE = "xsd:integer"
[docs] @classmethod def from_xcal_element(cls, element: ElementAdapter, params: Parameters) -> Self: """Parse xCal from :rfc:`6321`. Parameters: element: The xCal element to parse. Raises: ~error.XCalParsingError: If the provided xCal is invalid. """ try: value = int(element.get_xsd_token()) except (TypeError, ValueError) as e: raise XCalParsingError( f"Expected {cls.XCAL_TYPE}", element.get_xsd_token(), element, ) from e # xCal integers are xsd:integers. They do not have a value range. return cls(value, params=params, _validate_range=False)
[docs] @classmethod @from_xcal_wrapper def from_xcal_in_recur(cls, parser: XCalParser, params: Parameters) -> Self: """Parse xCal from :rfc:`6321`. Parameters: element: The xCal element to parse. Raises: ~error.XCalParsingError: If the provided xCal is invalid. """ element = parser.parse_tag() return cls.from_xcal_element(element, params)
[docs] def to_xcal(self, element: Element) -> None: """Add the xCal representation of this property according to :rfc:`6321`.""" self.params.to_xcal(element) element = SubElement(element, self.default_value.lower()) element.text = self.to_ical().decode()
[docs] class vNonNegativeInt(vInt): """This is an integer that is supposed to be at least 0. See https://www.rfc-editor.org/rfc/inline-errata/rfc6321.html#btn_3050 """ min: ClassVar[int] = 0
[docs] @classmethod def examples(cls) -> list[vInt]: """Examples of vPositiveInt.""" return [cls(1000), cls(0)]
XCAL_TYPE = "xsd:nonNegativeInteger"
__all__ = ["vInt", "vNonNegativeInt"]