Source code for ics.icalendar
import copy
import warnings
from typing import Dict, Iterable, Optional, Set, Union
from six import text_type
from .component import Component
from .event import Event
from ics.grammar.parse import Container, calendar_string_to_containers
from .timeline import Timeline
from .todo import Todo
from ics.parsers.icalendar_parser import CalendarParser
from ics.serializers.icalendar_serializer import CalendarSerializer
[docs]class Calendar(Component):
"""
Represents an unique rfc5545 iCalendar.
Attributes:
events: a set of Event contained in the Calendar
todos: a set of Todo contained in the Calendar
timeline: a Timeline instance linked to this Calendar
"""
class Meta:
name = 'VCALENDAR'
parser = CalendarParser
serializer = CalendarSerializer
[docs] def __init__(
self,
imports: Union[str, Container] = None,
events: Iterable[Event] = None,
todos: Iterable[Todo] = None,
creator: str = None
):
"""Instantiates a new Calendar.
Args:
imports (**str**): data to be imported into the Calendar,
events (**Set[Event]**): Events to be added to the calendar
todos (Set[Todo]): Todos to be added to the calendar
creator (string): uid of the creator program.
If ``imports`` is specified, every other argument will be ignored.
"""
self._timezones: Dict = {} # FIXME mypy
self.events: Set[Event] = set()
self.todos: Set[Todo] = set()
self.extra = Container(name='VCALENDAR')
self.scale = None
self.method = None
self.timeline = Timeline(self)
if imports is not None:
if isinstance(imports, Container):
self._populate(imports)
else:
containers = calendar_string_to_containers(imports)
if len(containers) != 1:
raise NotImplementedError(
'Multiple calendars in one file are not supported by this method. Use ics.Calendar.parse_multiple()')
self._populate(containers[0]) # Use first calendar
else:
if events is not None:
self.events.update(set(events))
if todos is not None:
self.todos.update(set(todos))
self._creator = creator
[docs] @classmethod
def parse_multiple(cls, string):
""""
Parses an input string that may contain mutiple calendars
and retruns a list of :class:`ics.event.Calendar`
"""
containers = calendar_string_to_containers(string)
return [cls(imports=c) for c in containers]
[docs] def __repr__(self) -> str:
return "<Calendar with {} event{} and {} todo{}>" \
.format(len(self.events),
"s" if len(self.events) > 1 else "",
len(self.todos),
"s" if len(self.todos) > 1 else "")
[docs] def __iter__(self) -> Iterable[str]:
"""Returns:
iterable: an iterable version of seralize(), line per line
(with line-endings).
Example:
Can be used to write calendar to a file:
>>> c = Calendar(); c.events.add(Event(name="My cool event"))
>>> open('my.ics', 'w').writelines(c)
"""
warnings.warn(
"Using Calendar as Iterable is deprecated and will be removed in version 0.8. "
"Use the explicit calendar.serialize_iter() instead.", DeprecationWarning)
yield from self.serialize_iter()
[docs] def __eq__(self, other: object) -> bool:
if not isinstance(other, Calendar):
raise NotImplementedError
for attr in ('extra', 'scale', 'method', 'creator'):
if self.__getattribute__(attr) != other.__getattribute__(attr):
return False
return (self.events == other.events) and (self.todos == other.todos)
[docs] def __ne__(self, other: object) -> bool:
return not self.__eq__(other)
@property
def creator(self) -> Optional[str]:
"""Get or set the calendar's creator.
| Will return a string.
| May be set to a string.
| Creator is the PRODID iCalendar property.
| It uniquely identifies the program that created the calendar.
"""
return self._creator
@creator.setter
def creator(self, value: Optional[str]) -> None:
if not isinstance(value, text_type):
raise ValueError('Event.creator must be unicode data not {}'.format(type(value)))
self._creator = value
[docs] def clone(self):
"""
Returns:
Calendar: an exact deep copy of self
"""
clone = copy.copy(self)
clone.extra = clone.extra.clone()
clone.events = copy.copy(self.events)
clone.todos = copy.copy(self.todos)
clone._timezones = copy.copy(self._timezones)
return clone