예제 #1
0
    def _periods(ps, timezone=str(get_localzone())):
        """Converts date period(s) to RDATE format.

        Period is defined as tuple of starting date/datetime and ending date/datetime or duration as Duration object:
            (date/datetime, date/datetime/Duration)

        :param ps: period or list of periods.
        :param timezone: Timezone formatted as an IANA Time Zone Database name, e.g. "Europe/Zurich". By default,
                         the computers local timezone is used if it is configured. UTC is used otherwise.
        :return: RDATE string of periods.
        """
        if not isinstance(ps, list):
            ps = [ps]

        period_strings = []
        for start, end in ps:
            if not isinstance(start, (date, datetime)):
                msg = 'The start object(s) must be a date or datetime, not {!r}.'.format(
                    end.__class__.__name__)
                raise TypeError(msg)

            start = insure_localisation(start, timezone)
            if isinstance(end, (date, datetime)):
                end = insure_localisation(end, timezone)
                pstr = '{}/{}'.format(start.strftime('%Y%m%dT%H%M%SZ'),
                                      end.strftime('%Y%m%dT%H%M%SZ'))
            elif isinstance(end, Duration):
                pstr = '{}/{}'.format(start.strftime('%Y%m%dT%H%M%SZ'), end)
            else:
                msg = 'The end object(s) must be a date, datetime or Duration, not {!r}.'.format(
                    end.__class__.__name__)
                raise TypeError(msg)
            period_strings.append(pstr)

        return 'VALUE=PERIOD:' + ','.join(period_strings)
예제 #2
0
    def test_to_object(self):
        event_json = {
            'summary': 'Good day',
            'description': 'Very good day indeed',
            'location': 'Prague',
            'start': {'dateTime': '2019-01-01T11:22:33', 'timeZone': TEST_TIMEZONE},
            'end': {'dateTime': '2019-01-01T12:22:33', 'timeZone': TEST_TIMEZONE},
            'recurrence': [
                'RRULE:FREQ=DAILY;WKST=SU',
                'EXRULE:FREQ=DAILY;BYDAY=MO;WKST=SU',
                'EXDATE:VALUE=DATE:20190419,20190422,20190512'
            ],
            'visibility': 'public',
            'reminders': {
                'useDefault': False,
                'overrides': [
                    {'method': 'popup', 'minutes': 30},
                    {'method': 'email', 'minutes': 120}
                ]
            },
            'attachments': [
                {
                    'title': 'My file1',
                    'fileUrl': 'https://file.url1',
                    'mimeType': 'application/vnd.google-apps.document'
                },
                {
                    'title': 'My file2',
                    'fileUrl': 'https://file.url2',
                    'mimeType': 'application/vnd.google-apps.document'
                }
            ]
        }

        event = EventSerializer.to_object(event_json)

        self.assertEqual(event.summary, 'Good day')
        self.assertEqual(event.start, insure_localisation((1 / Jan / 2019)[11:22:33], TEST_TIMEZONE))
        self.assertEqual(event.end, insure_localisation((1 / Jan / 2019)[12:22:33], TEST_TIMEZONE))
        self.assertEqual(event.description, 'Very good day indeed')
        self.assertEqual(event.location, 'Prague')
        self.assertEqual(len(event.recurrence), 3)
        self.assertEqual(event.visibility, Visibility.PUBLIC)
        self.assertIsInstance(event.reminders[0], PopupReminder)
        self.assertEqual(event.reminders[0].minutes_before_start, 30)
        self.assertIsInstance(event.reminders[1], EmailReminder)
        self.assertEqual(event.reminders[1].minutes_before_start, 120)
        self.assertEqual(len(event.attachments), 2)
        self.assertIsInstance(event.attachments[0], Attachment)
        self.assertEqual(event.attachments[0].title, 'My file1')
    def get_events(self,
                   time_min=None,
                   time_max=None,
                   order_by='startTime',
                   timezone=str(get_localzone())):
        """ Lists events

        :param time_min:
                staring date/datetime
        :param time_max:
                ending date/datetime
        :param order_by:
                order of the events. Possible values: "startTime", "updated".
        :param timezone:
                timezone formatted as an IANA Time Zone Database name, e.g. "Europe/Zurich". By default,
                the computers configured local timezone(if any) is used.
        :return:
        """
        time_min = time_min or datetime.utcnow()
        time_max = time_max or time_min + relativedelta(years=1)

        if not isinstance(time_min, datetime):
            time_min = datetime.combine(time_min, datetime.min.time())

        if not isinstance(time_max, datetime):
            time_max = datetime.combine(time_max, datetime.max.time())

        time_min = insure_localisation(time_min, timezone).isoformat()
        time_max = insure_localisation(time_max, timezone).isoformat()

        res = []
        page_token = None
        while True:
            events = self.service.events().list(
                calendarId=self.calendar,
                timeMin=time_min,
                timeMax=time_max,
                orderBy=order_by,
                singleEvents=True,
                pageToken=page_token).execute()
            for event_json in events['items']:
                event = EventSerializer(event_json).get_object()
                res.append(event)
            page_token = events.get('nextPageToken')
            if not page_token:
                break

        return res
예제 #4
0
    def test_init(self):
        event = Event(
            'Breakfast',
            start=(1 / Feb / 2019)[9:00],
            end=(31 / Dec / 2019)[23:59],
            timezone=TEST_TIMEZONE,
            description='Everyday breakfast',
            location='Home',
            recurrence=[
                Recurrence.rule(freq=DAILY),
                Recurrence.exclude_rule(by_week_day=[SU, SA]),
                Recurrence.exclude_dates([
                    19 / Apr / 2019,
                    22 / Apr / 2019,
                    12 / May / 2019
                ])
            ],
            visibility=Visibility.PRIVATE,
            minutes_before_popup_reminder=15
        )

        self.assertEqual(event.summary, 'Breakfast')
        self.assertEqual(event.start, insure_localisation((1 / Feb / 2019)[9:00], TEST_TIMEZONE))
        self.assertEqual(event.description, 'Everyday breakfast')
        self.assertEqual(event.location, 'Home')
        self.assertEqual(len(event.recurrence), 3)
        self.assertEqual(event.visibility, Visibility.PRIVATE)
        self.assertIsInstance(event.reminders[0], PopupReminder)
        self.assertEqual(event.reminders[0].minutes_before_start, 15)
예제 #5
0
    def test_init_no_end(self):
        start = 1 / Jun / 2019
        event = Event('Good day', start, timezone=TEST_TIMEZONE)
        self.assertEqual(event.end, start + 1 * days)

        start = insure_localisation((1 / Jul / 2019)[12:00], TEST_TIMEZONE)
        event = Event('Lunch', start, timezone=TEST_TIMEZONE)
        self.assertEqual(event.end, start + 1 * hours)
예제 #6
0
    def _times(dts, timezone=str(get_localzone())):
        """Converts datetime(s) set to RDATE format.

        :param dts: datetime object or list of datetime objects
        :param timezone: Timezone formatted as an IANA Time Zone Database name, e.g. "Europe/Zurich". By default,
                         the computers local timezone is used if it is configured. UTC is used otherwise.
        :return: RDATE string of datetimes with specified timezone.
        """

        if not isinstance(dts, list):
            dts = [dts]

        localized_datetimes = []
        for dt in dts:
            if not isinstance(dt, (date, datetime)):
                msg = 'The dts object(s) must be date or datetime, not {!r}.'.format(
                    dt.__class__.__name__)
                raise TypeError(msg)
            localized_datetimes.append(insure_localisation(dt, timezone))

        return 'TZID={}:{}'.format(
            timezone,
            ','.join(d.strftime('%Y%m%dT%H%M%S') for d in localized_datetimes))
예제 #7
0
    def __init__(self,
                 summary,
                 start,
                 end=None,
                 timezone=str(get_localzone()),
                 event_id=None,
                 description=None,
                 location=None,
                 recurrence=None,
                 color=None,
                 visibility=Visibility.DEFAULT,
                 gadget=None,
                 attachments=None,
                 reminders=None,
                 default_reminders=False,
                 minutes_before_popup_reminder=None,
                 minutes_before_email_reminder=None,
                 **other):
        """
        :param summary:
                title of the event.
        :param start:
                starting date/datetime.
        :param end:
                ending date/datetime. If 'end' is not specified, event is considered as a 1-day or 1-hour event
                if 'start' is date or datetime respectively.
        :param timezone:
                timezone formatted as an IANA Time Zone Database name, e.g. "Europe/Zurich". By default,
                the computers configured local timezone(if any) is used.
        :param event_id:
                opaque identifier of the event. By default is generated by the server. You can specify id as a
                5-1024 long string of characters used in base32hex ([a-vA-V0-9]). The ID must be unique per
                calendar.
        :param description:
                description of the event.
        :param location:
                geographic location of the event as free-form text.
        :param recurrence:
                RRULE/RDATE/EXRULE/EXDATE string or list of such strings. See :py:mod:`~gcsa.recurrence`
        :param color:
                color id referring to an entry from colors endpoint (list_event_colors)
        :param visibility:
                visibility of the event. Default is default visibility for events on the calendar.
        :param gadget:
                a gadget that extends the event. See :py:class:`~gcsa.gadget.Gadget`
        :param attachments:
                attachment or list of attachments. See :py:class:`~gcsa.attachment.Attachment`
        :param reminders:
                reminder or list of reminder objects. See :py:mod:`~gcsa.reminders`
        :param default_reminders:
                whether the default reminders of the calendar apply to the event.
        :param minutes_before_popup_reminder:
                minutes before popup reminder or None if reminder is not needed.
        :param minutes_before_email_reminder:
                minutes before email reminder or None if reminder is not needed.
        :param other:
                Other fields that should be included in request json. Will be included as they are.
        """
        def assure_list(obj):
            return [] if obj is None else obj if isinstance(obj,
                                                            list) else [obj]

        self.timezone = timezone
        self.start = start
        if end:
            self.end = end
        elif isinstance(start, datetime):
            self.end = start + timedelta(hours=1)
        elif isinstance(start, date):
            self.end = start + timedelta(days=1)

        if isinstance(self.start, datetime) and isinstance(self.end, datetime):
            self.start = insure_localisation(self.start, timezone)
            self.end = insure_localisation(self.end, timezone)
        elif isinstance(self.start, datetime) or isinstance(
                self.end, datetime):
            raise TypeError(
                'Start and end must either both be date or both be datetime.')

        reminders = assure_list(reminders)

        if len(reminders) > 5:
            raise ValueError('The maximum number of override reminders is 5.')

        if default_reminders and reminders:
            raise ValueError(
                'Cannot specify both default reminders and overrides at the same time.'
            )

        self.event_id = event_id and event_id.lower()
        self.summary = summary
        self.description = description
        self.location = location
        self.recurrence = assure_list(recurrence)
        self.color_id = color
        self.visibility = visibility
        self.gadget = gadget
        self.attachments = assure_list(attachments)
        self.reminders = reminders
        self.default_reminders = default_reminders
        self.other = other

        if minutes_before_popup_reminder is not None:
            self.add_popup_reminder(minutes_before_popup_reminder)
        if minutes_before_email_reminder is not None:
            self.add_email_reminder(minutes_before_email_reminder)
    def test_to_object(self):
        event_json = {
            'summary':
            'Good day',
            'description':
            'Very good day indeed',
            'location':
            'Prague',
            'start': {
                'dateTime': '2019-01-01T11:22:33',
                'timeZone': TEST_TIMEZONE
            },
            'end': {
                'dateTime': '2019-01-01T12:22:33',
                'timeZone': TEST_TIMEZONE
            },
            'recurrence': [
                'RRULE:FREQ=DAILY;WKST=SU',
                'EXRULE:FREQ=DAILY;BYDAY=MO;WKST=SU',
                'EXDATE:VALUE=DATE:20190419,20190422,20190512'
            ],
            'visibility':
            'public',
            'attendees': [
                {
                    'email': '*****@*****.**',
                    'responseStatus': ResponseStatus.NEEDS_ACTION
                },
                {
                    'email': '*****@*****.**',
                    'responseStatus': ResponseStatus.ACCEPTED
                },
            ],
            'reminders': {
                'useDefault':
                False,
                'overrides': [{
                    'method': 'popup',
                    'minutes': 30
                }, {
                    'method': 'email',
                    'minutes': 120
                }]
            },
            'attachments': [{
                'title': 'My file1',
                'fileUrl': 'https://file.url1',
                'mimeType': 'application/vnd.google-apps.document'
            }, {
                'title': 'My file2',
                'fileUrl': 'https://file.url2',
                'mimeType': 'application/vnd.google-apps.document'
            }]
        }

        serializer = EventSerializer(event_json)
        event = serializer.get_object()

        self.assertEqual(event.summary, 'Good day')
        self.assertEqual(
            event.start,
            insure_localisation((1 / Jan / 2019)[11:22:33], TEST_TIMEZONE))
        self.assertEqual(
            event.end,
            insure_localisation((1 / Jan / 2019)[12:22:33], TEST_TIMEZONE))
        self.assertEqual(event.description, 'Very good day indeed')
        self.assertEqual(event.location, 'Prague')
        self.assertEqual(len(event.recurrence), 3)
        self.assertEqual(event.visibility, Visibility.PUBLIC)
        self.assertEqual(len(event.attendees), 2)
        self.assertIsInstance(event.reminders[0], PopupReminder)
        self.assertEqual(event.reminders[0].minutes_before_start, 30)
        self.assertIsInstance(event.reminders[1], EmailReminder)
        self.assertEqual(event.reminders[1].minutes_before_start, 120)
        self.assertEqual(len(event.attachments), 2)
        self.assertIsInstance(event.attachments[0], Attachment)
        self.assertEqual(event.attachments[0].title, 'My file1')

        event_json_str = """{
            "summary": "Good day",
            "description": "Very good day indeed",
            "location": "Prague",
            "start": {"date": "2020-07-20"},
            "end": {"date": "2020-07-22"}
        }"""

        event = EventSerializer.to_object(event_json_str)

        self.assertEqual(event.summary, 'Good day')
        self.assertEqual(event.description, 'Very good day indeed')
        self.assertEqual(event.location, 'Prague')
        self.assertEqual(event.start, 20 / Jul / 2020)
        self.assertEqual(event.end, 22 / Jul / 2020)