Source code for icalendar.prop.factory

"""Factory class for all the property types."""

from __future__ import annotations

from typing import ClassVar

from icalendar.caselessdict import CaselessDict
from icalendar.prop.adr import vAdr
from icalendar.prop.binary import vBinary
from icalendar.prop.boolean import vBoolean
from icalendar.prop.cal_address import vCalAddress
from icalendar.prop.categories import vCategory
from icalendar.prop.dt import (
    vDate,
    vDatetime,
    vDDDLists,
    vDDDTypes,
    vDuration,
    vPeriod,
    vTime,
    vUTCOffset,
)
from icalendar.prop.float import vFloat
from icalendar.prop.geo import vGeo
from icalendar.prop.inline import vInline
from icalendar.prop.n import vN
from icalendar.prop.org import vOrg
from icalendar.prop.recur import vFrequency, vRecur, vWeekday
from icalendar.prop.text import vText
from icalendar.prop.uid import vUid
from icalendar.prop.unknown import vUnknown
from icalendar.prop.uri import vUri
from icalendar.prop.xml_reference import vXmlReference

from .integer import vInt


[docs] class TypesFactory(CaselessDict): """Factory for all value types defined in :rfc:`5545` and subsequent. The value and parameter names don't overlap. So one factory is enough for both kinds. """ _instance: ClassVar[TypesFactory | None] = None
[docs] def instance() -> TypesFactory: """Return a singleton instance of this class.""" if TypesFactory._instance is None: TypesFactory._instance = TypesFactory() return TypesFactory._instance
def __init__(self, *args, **kwargs): """Set keys to upper for initial dict""" super().__init__(*args, **kwargs) self.all_types = ( vBinary, vBoolean, vCalAddress, vDDDLists, vDDDTypes, vDate, vDatetime, vDuration, vFloat, vFrequency, vGeo, vInline, vInt, vPeriod, vRecur, vText, vTime, vUTCOffset, vUri, vWeekday, vCategory, vAdr, vN, vOrg, vUid, vXmlReference, vUnknown, ) self["binary"] = vBinary self["boolean"] = vBoolean self["cal-address"] = vCalAddress self["date"] = vDDDTypes self["date-time"] = vDDDTypes self["duration"] = vDDDTypes self["float"] = vFloat self["integer"] = vInt self["period"] = vPeriod self["recur"] = vRecur self["text"] = vText self["time"] = vTime self["uri"] = vUri self["utc-offset"] = vUTCOffset self["geo"] = vGeo self["inline"] = vInline self["date-time-list"] = vDDDLists self["categories"] = vCategory self["adr"] = vAdr # RFC 6350 vCard self["n"] = vN # RFC 6350 vCard self["org"] = vOrg # RFC 6350 vCard self["unknown"] = vUnknown # RFC 7265 self["uid"] = vUid # RFC 9253 self["xml-reference"] = vXmlReference # RFC 9253 ################################################# # Property types # These are the default types types_map = CaselessDict( { #################################### # Property value types # Calendar Properties "calscale": "text", "method": "text", "prodid": "text", "version": "text", # Descriptive Component Properties "attach": "uri", "categories": "categories", "class": "text", # vCard Properties (RFC 6350) "adr": "adr", "n": "n", "org": "org", "comment": "text", "description": "text", "geo": "geo", "location": "text", "percent-complete": "integer", "priority": "integer", "resources": "text", "status": "text", "summary": "text", # RFC 9253 # link should be uri, xml-reference or uid # uri is likely most helpful if people forget to set VALUE "link": "uri", "concept": "uri", "refid": "text", # Date and Time Component Properties "completed": "date-time", "dtend": "date-time", "due": "date-time", "dtstart": "date-time", "duration": "duration", "freebusy": "period", "transp": "text", "refresh-interval": "duration", # RFC 7986 # Time Zone Component Properties "tzid": "text", "tzname": "text", "tzoffsetfrom": "utc-offset", "tzoffsetto": "utc-offset", "tzurl": "uri", # Relationship Component Properties "attendee": "cal-address", "contact": "text", "organizer": "cal-address", "recurrence-id": "date-time", "related-to": "text", "url": "uri", "conference": "uri", # RFC 7986 "source": "uri", "uid": "text", # Recurrence Component Properties "exdate": "date-time-list", "exrule": "recur", "rdate": "date-time-list", "rrule": "recur", # Alarm Component Properties "action": "text", "repeat": "integer", "trigger": "duration", "acknowledged": "date-time", # Change Management Component Properties "created": "date-time", "dtstamp": "date-time", "last-modified": "date-time", "sequence": "integer", # Miscellaneous Component Properties "request-status": "text", #################################### # parameter types (luckily there is no name overlap) "altrep": "uri", "cn": "text", "cutype": "text", "delegated-from": "cal-address", "delegated-to": "cal-address", "dir": "uri", "encoding": "text", "fmttype": "text", "fbtype": "text", "language": "text", "member": "cal-address", "partstat": "text", "range": "text", "related": "text", "reltype": "text", "role": "text", "rsvp": "boolean", "sent-by": "cal-address", "value": "text", # rfc 9253 parameters "label": "text", "linkrel": "text", "gap": "duration", } )
[docs] def for_property(self, name, value_param: str | None = None) -> type: """Returns the type class for a property or parameter. Parameters: name: Property or parameter name value_param: Optional ``VALUE`` parameter, for example, "DATE", "DATE-TIME", or other string. Returns: The appropriate value type class. """ # Special case: RDATE and EXDATE always use vDDDLists to support list values # regardless of the VALUE parameter if name.upper() in ("RDATE", "EXDATE"): return self["date-time-list"] # Only use VALUE parameter for known properties that support multiple value # types (like DTSTART, DTEND, etc. which can be DATE or DATE-TIME) # For unknown/custom properties, always use the default type from types_map if value_param and name in self.types_map and value_param in self: return self[value_param] return self[self.types_map.get(name, "unknown")]
[docs] def to_ical(self, name, value): """Encodes a named value from a primitive python type to an icalendar encoded string. """ type_class = self.for_property(name) return type_class(value).to_ical()
[docs] def from_ical(self, name, value): """Decodes a named property or parameter value from an icalendar encoded string to a primitive python type. """ type_class = self.for_property(name) return type_class.from_ical(value)
__all__ = ["TypesFactory"]