Exemplo n.º 1
0
 def test_client_side_ordering_on_mixed_all_day_and_normal(self):
     # Test that client-side ordering on start and end fields works for items that are a mix of normal an all-day
     # items. This requires us to compare EWSDateTime -> EWSDate values which is not allowed by default (EWSDate ->
     # EWSDateTime *is* allowed).
     start = EWSDateTime(2016,
                         1,
                         1,
                         8,
                         tzinfo=self.account.default_timezone)
     end = EWSDateTime(2016, 1, 1, 10, tzinfo=self.account.default_timezone)
     all_day_date = (start - datetime.timedelta(days=1)).date()
     item1 = self.ITEM_CLASS(
         account=self.account,
         folder=self.test_folder,
         subject=get_random_string(16),
         start=all_day_date,
         end=all_day_date,
         is_all_day=True,
         categories=self.categories,
     )
     item2 = self.ITEM_CLASS(
         account=self.account,
         folder=self.test_folder,
         subject=get_random_string(16),
         start=start,
         end=end,
         categories=self.categories,
     )
     self.test_folder.bulk_create(items=[item1, item2])
     list(
         self.test_folder.view(start=start - datetime.timedelta(days=1),
                               end=end).order_by('start'))
     list(
         self.test_folder.view(start=start - datetime.timedelta(days=1),
                               end=end).order_by('-start'))
Exemplo n.º 2
0
    def test_ewsdatetime(self):
        tz = EWSTimeZone.timezone('Europe/Copenhagen')
        self.assertIsInstance(tz, EWSTimeZone)
        self.assertEqual(tz.ms_id, 'Romance Standard Time')
        self.assertEqual(tz.ms_name, '(UTC+01:00) Brussels, Copenhagen, Madrid, Paris')

        dt = tz.localize(EWSDateTime(2000, 1, 2, 3, 4, 5))
        self.assertIsInstance(dt, EWSDateTime)
        self.assertIsInstance(dt.tzinfo, EWSTimeZone)
        self.assertEqual(dt.tzinfo.ms_id, tz.ms_id)
        self.assertEqual(dt.tzinfo.ms_name, tz.ms_name)
        self.assertEqual(str(dt), '2000-01-02 03:04:05+01:00')
        self.assertEqual(
            repr(dt),
            "EWSDateTime(2000, 1, 2, 3, 4, 5, tzinfo=<DstTzInfo 'Europe/Copenhagen' CET+1:00:00 STD>)"
        )
        self.assertIsInstance(dt + timedelta(days=1), EWSDateTime)
        self.assertIsInstance(dt - timedelta(days=1), EWSDateTime)
        self.assertIsInstance(dt - EWSDateTime.now(tz=tz), timedelta)
        self.assertIsInstance(EWSDateTime.now(tz=tz), EWSDateTime)
        self.assertEqual(dt, EWSDateTime.from_datetime(tz.localize(datetime(2000, 1, 2, 3, 4, 5))))
        self.assertEqual(dt.ewsformat(), '2000-01-02T03:04:05')
        utc_tz = EWSTimeZone.timezone('UTC')
        self.assertEqual(dt.astimezone(utc_tz).ewsformat(), '2000-01-02T02:04:05Z')
        # Test summertime
        dt = tz.localize(EWSDateTime(2000, 8, 2, 3, 4, 5))
        self.assertEqual(dt.astimezone(utc_tz).ewsformat(), '2000-08-02T01:04:05Z')
Exemplo n.º 3
0
    def test_delete_occurrence_via_index(self):
        # Test deleting occurrences via occurrence index without knowing the ID of the occurrence.
        start = EWSDateTime(2016,
                            1,
                            1,
                            8,
                            tzinfo=self.account.default_timezone)
        end = EWSDateTime(2016, 1, 1, 10, tzinfo=self.account.default_timezone)
        master_item = self.ITEM_CLASS(
            folder=self.test_folder,
            start=start,
            end=end,
            subject=get_random_string(16),
            recurrence=Recurrence(pattern=DailyPattern(interval=1),
                                  start=start.date(),
                                  number=4),
            categories=self.categories,
        ).save()

        # Delete the third occurrence
        third_occurrence = master_item.occurrence(index=3)
        third_occurrence.refresh()  # Test that GetItem works

        third_occurrence = master_item.occurrence(index=3)
        third_occurrence.delete()  # Test that DeleteItem works

        # Test change on the master item
        master_item.refresh()
        self.assertEqual(master_item.modified_occurrences, None)
        self.assertEqual(len(master_item.deleted_occurrences), 1)
        deleted_occurrence = master_item.deleted_occurrences[0]
        self.assertIsInstance(deleted_occurrence, DeletedOccurrence)
        self.assertEqual(deleted_occurrence.start,
                         start + datetime.timedelta(days=2))
Exemplo n.º 4
0
    def test_task_validation(self):
        tz = self.account.default_timezone
        task = Task(due_date=EWSDate(2017, 1, 1), start_date=EWSDate(2017, 2, 1))
        task.clean()
        # We reset due date if it's before start date
        self.assertEqual(task.due_date, EWSDate(2017, 2, 1))
        self.assertEqual(task.due_date, task.start_date)

        task = Task(complete_date=EWSDateTime(2099, 1, 1, tzinfo=tz), status=Task.NOT_STARTED)
        task.clean()
        # We reset status if complete_date is set
        self.assertEqual(task.status, Task.COMPLETED)
        # We also reset complete date to now() if it's in the future
        self.assertEqual(task.complete_date.date(), UTC_NOW().date())

        task = Task(complete_date=EWSDateTime(2017, 1, 1, tzinfo=tz), start_date=EWSDate(2017, 2, 1))
        task.clean()
        # We also reset complete date to start_date if it's before start_date
        self.assertEqual(task.complete_date.date(), task.start_date)

        task = Task(percent_complete=Decimal('50.0'), status=Task.COMPLETED)
        task.clean()
        # We reset percent_complete to 100.0 if state is completed
        self.assertEqual(task.percent_complete, Decimal(100))

        task = Task(percent_complete=Decimal('50.0'), status=Task.NOT_STARTED)
        task.clean()
        # We reset percent_complete to 0.0 if state is not_started
        self.assertEqual(task.percent_complete, Decimal(0))
Exemplo n.º 5
0
    def test_change_occurrence(self):
        # Test that we can make changes to individual occurrences and see the effect on the master item.
        start = EWSDateTime(2016,
                            1,
                            1,
                            8,
                            tzinfo=self.account.default_timezone)
        end = EWSDateTime(2016, 1, 1, 10, tzinfo=self.account.default_timezone)
        master_item = self.ITEM_CLASS(
            folder=self.test_folder,
            start=start,
            end=end,
            recurrence=Recurrence(pattern=DailyPattern(interval=1),
                                  start=start.date(),
                                  number=4),
            categories=self.categories,
        ).save()
        master_item.refresh()

        # Test occurrences as full calendar items, unfolded from the master
        range_start, range_end = start, end + datetime.timedelta(days=3)
        unfolded = [
            i for i in self.test_folder.view(start=range_start, end=range_end)
            if self.match_cat(i)
        ]

        # Change the start and end of the second occurrence
        second_occurrence = unfolded[1]
        second_occurrence.start += datetime.timedelta(hours=1)
        second_occurrence.end += datetime.timedelta(hours=1)
        second_occurrence.save()

        # Test change on the master item
        master_item.refresh()
        self.assertEqual(len(master_item.modified_occurrences), 1)
        modified_occurrence = master_item.modified_occurrences[0]
        self.assertIsInstance(modified_occurrence, Occurrence)
        self.assertEqual(modified_occurrence.id, second_occurrence.id)
        self.assertEqual(modified_occurrence.start, second_occurrence.start)
        self.assertEqual(modified_occurrence.end, second_occurrence.end)
        self.assertEqual(modified_occurrence.original_start,
                         second_occurrence.start - datetime.timedelta(hours=1))
        self.assertEqual(master_item.deleted_occurrences, None)

        # Test change on the unfolded item
        unfolded = [
            i for i in self.test_folder.view(start=range_start, end=range_end)
            if self.match_cat(i)
        ]
        self.assertEqual(len(unfolded), 4)
        self.assertEqual(unfolded[1].type, EXCEPTION)
        self.assertEqual(unfolded[1].start, second_occurrence.start)
        self.assertEqual(unfolded[1].end, second_occurrence.end)
        self.assertEqual(unfolded[1].original_start,
                         second_occurrence.start - datetime.timedelta(hours=1))
Exemplo n.º 6
0
def get_random_datetime(start_date=EWSDate(1996, 1, 1), end_date=EWSDate(2030, 1, 1), tz=UTC):
    # Create a random datetime with minute precision. Both dates are inclusive.
    # Keep with a reasonable date range. A wider date range than the default values is unstable WRT timezones.
    random_date = get_random_date(start_date=start_date, end_date=end_date)
    random_datetime = datetime.datetime.combine(random_date, datetime.time.min) \
        + datetime.timedelta(minutes=random.randint(0, 60 * 24))
    return EWSDateTime.from_datetime(random_datetime).replace(tzinfo=tz)
Exemplo n.º 7
0
    def test_change_occurrence_via_index(self):
        # Test updating occurrences via occurrence index without knowing the ID of the occurrence.
        start = EWSDateTime(2016,
                            1,
                            1,
                            8,
                            tzinfo=self.account.default_timezone)
        end = EWSDateTime(2016, 1, 1, 10, tzinfo=self.account.default_timezone)
        master_item = self.ITEM_CLASS(
            folder=self.test_folder,
            start=start,
            end=end,
            subject=get_random_string(16),
            recurrence=Recurrence(pattern=DailyPattern(interval=1),
                                  start=start.date(),
                                  number=4),
            categories=self.categories,
        ).save()

        # Change the start and end of the second occurrence
        second_occurrence = master_item.occurrence(index=2)
        second_occurrence.start = start + datetime.timedelta(days=1, hours=1)
        second_occurrence.end = end + datetime.timedelta(days=1, hours=1)
        second_occurrence.save(update_fields=[
            'start', 'end'
        ])  # Test that UpdateItem works with only a few fields

        second_occurrence = master_item.occurrence(index=2)
        second_occurrence.refresh()
        self.assertEqual(second_occurrence.subject, master_item.subject)
        second_occurrence.start += datetime.timedelta(hours=1)
        second_occurrence.end += datetime.timedelta(hours=1)
        second_occurrence.save(
            update_fields=['start',
                           'end'])  # Test that UpdateItem works after refresh

        # Test change on the master item
        master_item.refresh()
        self.assertEqual(len(master_item.modified_occurrences), 1)
        modified_occurrence = master_item.modified_occurrences[0]
        self.assertIsInstance(modified_occurrence, Occurrence)
        self.assertEqual(modified_occurrence.id, second_occurrence.id)
        self.assertEqual(modified_occurrence.start, second_occurrence.start)
        self.assertEqual(modified_occurrence.end, second_occurrence.end)
        self.assertEqual(modified_occurrence.original_start,
                         second_occurrence.start - datetime.timedelta(hours=2))
        self.assertEqual(master_item.deleted_occurrences, None)
Exemplo n.º 8
0
    def test_get_master_recurrence(self):
        # Test getting the master recurrence via an occurrence
        start = EWSDateTime(2016,
                            1,
                            1,
                            8,
                            tzinfo=self.account.default_timezone)
        end = EWSDateTime(2016, 1, 1, 10, tzinfo=self.account.default_timezone)
        recurrence = Recurrence(pattern=DailyPattern(interval=1),
                                start=start.date(),
                                number=4)
        master_item = self.ITEM_CLASS(
            folder=self.test_folder,
            start=start,
            end=end,
            subject=get_random_string(16),
            recurrence=recurrence,
            categories=self.categories,
        ).save()

        # Get the master from an occurrence
        range_start, range_end = start, end + datetime.timedelta(days=3)
        unfolded = [
            i for i in self.test_folder.view(start=range_start, end=range_end)
            if self.match_cat(i)
        ]
        third_occurrence = unfolded[2]
        self.assertEqual(third_occurrence.recurrence, None)
        master_from_occurrence = third_occurrence.recurring_master()

        master_from_occurrence.refresh()  # Test that GetItem works
        self.assertEqual(master_from_occurrence.recurrence, recurrence)
        self.assertEqual(master_from_occurrence.subject, master_item.subject)

        master_from_occurrence = third_occurrence.recurring_master()
        master_from_occurrence.subject = get_random_string(16)
        master_from_occurrence.save(
            update_fields=['subject'])  # Test that UpdateItem works
        master_from_occurrence.delete()  # Test that DeleteItem works

        with self.assertRaises(ErrorItemNotFound):
            master_item.delete(
            )  # Item is gone from the server, so this should fail
        with self.assertRaises(ErrorItemNotFound):
            third_occurrence.delete(
            )  # Item is gone from the server, so this should fail
Exemplo n.º 9
0
    def test_delete_occurrence(self):
        # Test that we can delete an occurrence and see the cange on the master item
        start = EWSDateTime(2016,
                            1,
                            1,
                            8,
                            tzinfo=self.account.default_timezone)
        end = EWSDateTime(2016, 1, 1, 10, tzinfo=self.account.default_timezone)
        master_item = self.ITEM_CLASS(
            folder=self.test_folder,
            start=start,
            end=end,
            recurrence=Recurrence(pattern=DailyPattern(interval=1),
                                  start=start.date(),
                                  number=4),
            categories=self.categories,
        ).save()
        master_item.refresh()

        # Test occurrences as full calendar items, unfolded from the master
        range_start, range_end = start, end + datetime.timedelta(days=3)
        unfolded = [
            i for i in self.test_folder.view(start=range_start, end=range_end)
            if self.match_cat(i)
        ]

        # Delete the third occurrence
        third_occurrence = unfolded[2]
        third_occurrence.delete()

        # Test change on the master item
        master_item.refresh()
        self.assertEqual(master_item.modified_occurrences, None)
        self.assertEqual(len(master_item.deleted_occurrences), 1)
        deleted_occurrence = master_item.deleted_occurrences[0]
        self.assertIsInstance(deleted_occurrence, DeletedOccurrence)
        self.assertEqual(deleted_occurrence.start, third_occurrence.start)

        # Test change on the unfolded items
        unfolded = [
            i for i in self.test_folder.view(start=range_start, end=range_end)
            if self.match_cat(i)
        ]
        self.assertEqual(len(unfolded), 3)
Exemplo n.º 10
0
def get_random_datetime(start_date=EWSDate(1996, 1, 1), end_date=EWSDate(2030, 1, 1), tz=UTC):
    # Create a random datetime with minute precision. Both dates are inclusive.
    # Keep with a reasonable date range. A wider date range than the default values is unstable WRT timezones.
    while True:
        try:
            random_date = get_random_date(start_date=start_date, end_date=end_date)
            random_datetime = datetime.datetime.combine(random_date, datetime.time.min) \
                + datetime.timedelta(minutes=random.randint(0, 60 * 24))
            return tz.localize(EWSDateTime.from_datetime(random_datetime), is_dst=None)
        except (AmbiguousTimeError, NonExistentTimeError):
            pass
Exemplo n.º 11
0
    def test_task_validation(self):
        tz = EWSTimeZone.timezone('Europe/Copenhagen')
        task = Task(due_date=tz.localize(EWSDateTime(2017, 1, 1)),
                    start_date=tz.localize(EWSDateTime(2017, 2, 1)))
        task.clean()
        # We reset due date if it's before start date
        self.assertEqual(task.due_date, tz.localize(EWSDateTime(2017, 2, 1)))
        self.assertEqual(task.due_date, task.start_date)

        task = Task(complete_date=tz.localize(EWSDateTime(2099, 1, 1)),
                    status=Task.NOT_STARTED)
        task.clean()
        # We reset status if complete_date is set
        self.assertEqual(task.status, Task.COMPLETED)
        # We also reset complete date to now() if it's in the future
        self.assertEqual(task.complete_date.date(), UTC_NOW().date())

        task = Task(complete_date=tz.localize(EWSDateTime(2017, 1, 1)),
                    start_date=tz.localize(EWSDateTime(2017, 2, 1)))
        task.clean()
        # We also reset complete date to start_date if it's before start_date
        self.assertEqual(task.complete_date, task.start_date)

        task = Task(percent_complete=Decimal('50.0'), status=Task.COMPLETED)
        task.clean()
        # We reset percent_complete to 100.0 if state is completed
        self.assertEqual(task.percent_complete, Decimal(100))

        task = Task(percent_complete=Decimal('50.0'), status=Task.NOT_STARTED)
        task.clean()
        # We reset percent_complete to 0.0 if state is not_started
        self.assertEqual(task.percent_complete, Decimal(0))
Exemplo n.º 12
0
 def test_localize(self):
     # Test some corner cases around DST
     tz = EWSTimeZone('Europe/Copenhagen')
     with warnings.catch_warnings():
         # localize() is deprecated but we still want to test it. Silence the DeprecationWarning
         warnings.simplefilter("ignore")
         self.assertEqual(
             str(
                 tz.localize(EWSDateTime(2023, 10, 29, 2, 36, 0),
                             is_dst=False)), '2023-10-29 02:36:00+01:00')
         self.assertEqual(
             str(
                 tz.localize(EWSDateTime(2023, 10, 29, 2, 36, 0),
                             is_dst=None)), '2023-10-29 02:36:00+02:00')
         self.assertEqual(
             str(
                 tz.localize(EWSDateTime(2023, 10, 29, 2, 36, 0),
                             is_dst=True)), '2023-10-29 02:36:00+02:00')
         self.assertEqual(
             str(
                 tz.localize(EWSDateTime(2023, 3, 26, 2, 36, 0),
                             is_dst=False)), '2023-03-26 02:36:00+01:00')
         self.assertEqual(
             str(
                 tz.localize(EWSDateTime(2023, 3, 26, 2, 36, 0),
                             is_dst=None)), '2023-03-26 02:36:00+01:00')
         self.assertEqual(
             str(
                 tz.localize(EWSDateTime(2023, 3, 26, 2, 36, 0),
                             is_dst=True)), '2023-03-26 02:36:00+02:00')
Exemplo n.º 13
0
 def test_super_methods(self):
     tz = EWSTimeZone('Europe/Copenhagen')
     self.assertIsInstance(EWSDateTime.now(), EWSDateTime)
     self.assertIsInstance(EWSDateTime.now(tz=tz), EWSDateTime)
     self.assertIsInstance(EWSDateTime.utcnow(), EWSDateTime)
     self.assertIsInstance(EWSDateTime.fromtimestamp(123456789), EWSDateTime)
     self.assertIsInstance(EWSDateTime.fromtimestamp(123456789, tz=tz), EWSDateTime)
     self.assertIsInstance(EWSDateTime.utcfromtimestamp(123456789), EWSDateTime)
Exemplo n.º 14
0
    def test_ewsdatetime(self):
        # Test a static timezone
        tz = EWSTimeZone('Etc/GMT-5')
        dt = EWSDateTime(2000, 1, 2, 3, 4, 5, tzinfo=tz)
        self.assertIsInstance(dt, EWSDateTime)
        self.assertIsInstance(dt.tzinfo, EWSTimeZone)
        self.assertEqual(dt.tzinfo.ms_id, tz.ms_id)
        self.assertEqual(dt.tzinfo.ms_name, tz.ms_name)
        self.assertEqual(str(dt), '2000-01-02 03:04:05+05:00')
        self.assertEqual(
            repr(dt),
            "EWSDateTime(2000, 1, 2, 3, 4, 5, tzinfo=EWSTimeZone(key='Etc/GMT-5'))"
        )

        # Test a DST timezone
        tz = EWSTimeZone('Europe/Copenhagen')
        dt = EWSDateTime(2000, 1, 2, 3, 4, 5, tzinfo=tz)
        self.assertIsInstance(dt, EWSDateTime)
        self.assertIsInstance(dt.tzinfo, EWSTimeZone)
        self.assertEqual(dt.tzinfo.ms_id, tz.ms_id)
        self.assertEqual(dt.tzinfo.ms_name, tz.ms_name)
        self.assertEqual(str(dt), '2000-01-02 03:04:05+01:00')
        self.assertEqual(
            repr(dt),
            "EWSDateTime(2000, 1, 2, 3, 4, 5, tzinfo=EWSTimeZone(key='Europe/Copenhagen'))"
        )

        # Test from_string
        with self.assertRaises(NaiveDateTimeNotAllowed):
            EWSDateTime.from_string('2000-01-02T03:04:05')
        self.assertEqual(EWSDateTime.from_string('2000-01-02T03:04:05+01:00'),
                         EWSDateTime(2000, 1, 2, 2, 4, 5, tzinfo=UTC))
        self.assertEqual(EWSDateTime.from_string('2000-01-02T03:04:05Z'),
                         EWSDateTime(2000, 1, 2, 3, 4, 5, tzinfo=UTC))
        self.assertIsInstance(
            EWSDateTime.from_string('2000-01-02T03:04:05+01:00'), EWSDateTime)
        self.assertIsInstance(EWSDateTime.from_string('2000-01-02T03:04:05Z'),
                              EWSDateTime)

        # Test addition, subtraction, summertime etc
        self.assertIsInstance(dt + datetime.timedelta(days=1), EWSDateTime)
        self.assertIsInstance(dt - datetime.timedelta(days=1), EWSDateTime)
        self.assertIsInstance(dt - EWSDateTime.now(tz=tz), datetime.timedelta)
        self.assertIsInstance(EWSDateTime.now(tz=tz), EWSDateTime)

        # Test various input for from_datetime()
        self.assertEqual(
            dt,
            EWSDateTime.from_datetime(
                datetime.datetime(2000,
                                  1,
                                  2,
                                  3,
                                  4,
                                  5,
                                  tzinfo=EWSTimeZone('Europe/Copenhagen'))))
        self.assertEqual(
            dt,
            EWSDateTime.from_datetime(
                datetime.datetime(
                    2000,
                    1,
                    2,
                    3,
                    4,
                    5,
                    tzinfo=zoneinfo.ZoneInfo('Europe/Copenhagen'))))
        self.assertEqual(
            dt,
            EWSDateTime.from_datetime(
                datetime.datetime(
                    2000,
                    1,
                    2,
                    3,
                    4,
                    5,
                    tzinfo=dateutil.tz.gettz('Europe/Copenhagen'))))
        self.assertEqual(
            dt,
            EWSDateTime.from_datetime(
                datetime.datetime(2000,
                                  1,
                                  2,
                                  3,
                                  4,
                                  5,
                                  tzinfo=pytz.timezone('Europe/Copenhagen'))))

        self.assertEqual(dt.ewsformat(), '2000-01-02T03:04:05+01:00')
        utc_tz = EWSTimeZone('UTC')
        self.assertEqual(
            dt.astimezone(utc_tz).ewsformat(), '2000-01-02T02:04:05Z')
        # Test summertime
        dt = EWSDateTime(2000, 8, 2, 3, 4, 5, tzinfo=tz)
        self.assertEqual(
            dt.astimezone(utc_tz).ewsformat(), '2000-08-02T01:04:05Z')

        # Test in-place add and subtract
        dt = EWSDateTime(2000, 1, 2, 3, 4, 5, tzinfo=tz)
        dt += datetime.timedelta(days=1)
        self.assertIsInstance(dt, EWSDateTime)
        self.assertEqual(dt, EWSDateTime(2000, 1, 3, 3, 4, 5, tzinfo=tz))
        dt = EWSDateTime(2000, 1, 2, 3, 4, 5, tzinfo=tz)
        dt -= datetime.timedelta(days=1)
        self.assertIsInstance(dt, EWSDateTime)
        self.assertEqual(dt, EWSDateTime(2000, 1, 1, 3, 4, 5, tzinfo=tz))

        # Test ewsformat() failure
        dt = EWSDateTime(2000, 1, 2, 3, 4, 5)
        with self.assertRaises(ValueError):
            dt.ewsformat()
        # Test wrong tzinfo type
        with self.assertRaises(ValueError):
            EWSDateTime(2000,
                        1,
                        2,
                        3,
                        4,
                        5,
                        tzinfo=pytz.timezone('Europe/Copenhagen'))
        with self.assertRaises(ValueError):
            EWSDateTime.from_datetime(EWSDateTime(2000, 1, 2, 3, 4, 5))
Exemplo n.º 15
0
    def test_view(self):
        item1 = self.ITEM_CLASS(
            account=self.account,
            folder=self.test_folder,
            subject=get_random_string(16),
            start=EWSDateTime(2016,
                              1,
                              1,
                              8,
                              tzinfo=self.account.default_timezone),
            end=EWSDateTime(2016,
                            1,
                            1,
                            10,
                            tzinfo=self.account.default_timezone),
            categories=self.categories,
        )
        item2 = self.ITEM_CLASS(
            account=self.account,
            folder=self.test_folder,
            subject=get_random_string(16),
            start=EWSDateTime(2016,
                              2,
                              1,
                              8,
                              tzinfo=self.account.default_timezone),
            end=EWSDateTime(2016,
                            2,
                            1,
                            10,
                            tzinfo=self.account.default_timezone),
            categories=self.categories,
        )
        self.test_folder.bulk_create(items=[item1, item2])
        qs = self.test_folder.view(start=item1.start, end=item2.end)

        # Test missing args
        with self.assertRaises(TypeError):
            self.test_folder.view()
        # Test bad args
        with self.assertRaises(ValueError):
            list(self.test_folder.view(start=item1.end, end=item1.start))
        with self.assertRaises(TypeError):
            list(self.test_folder.view(start='xxx', end=item1.end))
        with self.assertRaises(ValueError):
            list(
                self.test_folder.view(start=item1.start,
                                      end=item1.end,
                                      max_items=0))

        # Test dates
        self.assertEqual(
            len([
                i for i in self.test_folder.view(start=item1.start,
                                                 end=item1.end)
                if self.match_cat(i)
            ]), 1)
        self.assertEqual(
            len([
                i for i in self.test_folder.view(start=item1.start,
                                                 end=item2.end)
                if self.match_cat(i)
            ]), 2)
        # Edge cases. Get view from end of item1 to start of item2. Should logically return 0 items, but Exchange wants
        # it differently and returns item1 even though there is no overlap.
        self.assertEqual(
            len([
                i for i in self.test_folder.view(start=item1.end,
                                                 end=item2.start)
                if self.match_cat(i)
            ]), 1)
        self.assertEqual(
            len([
                i for i in self.test_folder.view(start=item1.start,
                                                 end=item2.start)
                if self.match_cat(i)
            ]), 1)

        # Test max_items
        self.assertEqual(
            len([
                i for i in self.test_folder.view(
                    start=item1.start, end=item2.end, max_items=9999)
                if self.match_cat(i)
            ]), 2)
        self.assertEqual(
            self.test_folder.view(start=item1.start,
                                  end=item2.end,
                                  max_items=1).count(), 1)

        # Test client-side ordering
        self.assertListEqual(
            [i.subject for i in qs.order_by('subject') if self.match_cat(i)],
            sorted([item1.subject, item2.subject]))
        # Test client-side ordering on a field with no default value and no default value_cls value
        self.assertListEqual(
            [i.start for i in qs.order_by('-start') if self.match_cat(i)],
            [item2.start, item1.start])
        # Test client-side ordering on multiple fields. Intentionally sort first on a field where values are equal,
        # to see that we can sort on the 2nd field.
        self.assertListEqual([
            i.start
            for i in qs.order_by('categories', '-start') if self.match_cat(i)
        ], [item2.start, item1.start])

        # Test chaining
        self.assertTrue(qs.count() >= 2)
        with self.assertRaises(ErrorInvalidOperation):
            qs.filter(subject=item1.subject).count(
            )  # EWS does not allow restrictions
        self.assertListEqual([
            i for i in qs.order_by('subject').values('subject')
            if i['subject'] in (item1.subject, item2.subject)
        ], [{
            'subject': s
        } for s in sorted([item1.subject, item2.subject])])
Exemplo n.º 16
0
def get_random_datetime(start_date=date(1900, 1, 1), end_date=date(2100, 1, 1)):
    # Create a random datetime with minute precision
    random_date = get_random_date(start_date=start_date, end_date=end_date)
    random_datetime = datetime.combine(random_date, time.min) + timedelta(minutes=random.randint(0, 60*24))
    return UTC.localize(EWSDateTime.from_datetime(random_datetime))
Exemplo n.º 17
0
def addEvent(calendarName, eventName, eventDescription, eventStartDate,
             eventEndDate):
    """ Add a new event to a calendar
    
    eventDescription can be empty
    eventDuration is calculated later by using eventStartDate and eventEndDate
    calendarName is stored as an Outlook calendar category
    """
    conn, cursor, tz, account = initEventStorage()
    # calendarName in lowercase to handle problems with finding it in database
    calendarName = calendarName.lower()
    if not checkIfCalendarExists(calendarName):
        return False, "Calendar {0} does not exist".format(calendarName)

    if not eventName:
        return False, "Event name is empty"

    try:
        convEventStartDate = datetime.datetime.strptime(
            eventStartDate, "%d.%m.%Y %H:%M")
    except ValueError:
        return False, "Event start date {0} could not be converted to date, Date format should be: %d.%m.%Y %H:%M".format(
            eventStartDate)

    try:
        convEventEndDate = datetime.datetime.strptime(eventEndDate,
                                                      "%d.%m.%Y %H:%M")
    except ValueError:
        return False, "Event end date {0} could not be converted to date, Date format should be: %d.%m.%Y %H:%M".format(
            eventEndDate)

    timeDuration = convEventEndDate - convEventStartDate
    if timeDuration < datetime.timedelta(0):
        return False, "Event duration is negative, please check start date {0} and end date {1}".format(
            convEventStartDate, convEventEndDate)
    eventDuration = str(timeDuration)

    # Add event to sqlite calendar
    addEventToSQLCalendar = "INSERT INTO '{0}' (eventName, eventDescription, eventStartDate, eventEndDate, eventDuration) VALUES ('{1}', '{2}', '{3}', '{4}', '{5}')".format(
        calendarName, eventName, eventDescription, convEventStartDate,
        convEventEndDate, eventDuration)
    conn.execute(addEventToSQLCalendar)
    conn.commit()

    # Create and add event to outlook calendar
    # A list of calendar items is required, so let us create one.
    calendar_items = []
    calendar_items.append(
        CalendarItem(
            start=tz.localize(
                EWSDateTime(convEventStartDate.year, convEventStartDate.month,
                            convEventStartDate.day, convEventStartDate.hour,
                            convEventStartDate.minute,
                            convEventStartDate.second,
                            convEventStartDate.microsecond)),
            end=tz.localize(
                EWSDateTime(convEventEndDate.year, convEventEndDate.month,
                            convEventEndDate.day, convEventEndDate.hour,
                            convEventEndDate.minute, convEventEndDate.second,
                            convEventEndDate.microsecond)),
            subject=eventName,
            body=eventDescription,
            location='empty',
            categories=[calendarName],
        ))
    res = account.calendar.add_items(calendar_items)

    return True, "Event {0} created".format(eventName)
Exemplo n.º 18
0
def showAgenda(calendarName='',
               eventStartDate='',
               eventEndDate='',
               deleteAfterwards=False):
    """ 
    Shows Agenda using the calendar in Outlook

    If no calendarName is given which is used as a category all events are shown
    if calendarName is given only events of this category are shown
    if start and end date are given the agenda of this time span is shown, otherwise agenda of today is shown.
    """
    conn, cursor, tz, account = initEventStorage()
    # calendarName in lowercase to handle problems with finding it in database
    calendarName = calendarName.lower()
    # Strip whitespace
    calendarName = calendarName.strip()
    # Check if calendar exists otherwise, we cannot show its agenda
    if calendarName == '':
        calendarCategory = None
    elif checkIfCalendarExists(calendarName):
        calendarCategory = [calendarName]
    else:
        return False, "Calendar {0} does not exist, agenda cannot be shown. Try command without stating a calendar".format(
            calendarName)

    # If start and end date is given check if it is a positive time span
    if eventStartDate or eventEndDate:
        try:
            convEventStartDate = datetime.datetime.strptime(
                eventStartDate, "%d.%m.%Y %H:%M")
        except ValueError:
            try:
                convEventStartDate = datetime.datetime.strptime(
                    eventStartDate, "%d.%m.%Y")
                convEventStartDate = convEventStartDate.replace(hour=0,
                                                                minute=00)
            except ValueError:
                return False, "Event start date {0} could not be converted to date, Date format should be either: %d.%m.%Y or: %d.%m.%Y %H:%M".format(
                    eventStartDate)

        try:
            convEventEndDate = datetime.datetime.strptime(
                eventEndDate, "%d.%m.%Y %H:%M")
        except ValueError:
            try:
                convEventEndDate = datetime.datetime.strptime(
                    eventEndDate, "%d.%m.%Y")
                convEventEndDate = convEventEndDate.replace(hour=23, minute=59)
            except ValueError:
                return False, "Event end date {0} could not be converted to date, Date format should be either: %d.%m.%Y or: %d.%m.%Y %H:%M".format(
                    eventEndDate)

        timeDuration = convEventEndDate - convEventStartDate
        if timeDuration < datetime.timedelta(0):
            return False, "Event duration is negative, please check start date {0} and end date {1}".format(
                convEventStartDate, convEventEndDate)
        eventDuration = str(timeDuration)
    # use today for the agenda
    else:
        nowDate = datetime.datetime.now()
        convEventStartDate = nowDate.replace(hour=0, minute=00)
        convEventEndDate = nowDate.replace(hour=23, minute=59)

    # Get Exchange ID and of the calendar items
    try:
        startDate = tz.localize(
            EWSDateTime(convEventStartDate.year, convEventStartDate.month,
                        convEventStartDate.day, convEventStartDate.hour,
                        convEventStartDate.minute))
        endDate = tz.localize(
            EWSDateTime(convEventEndDate.year, convEventEndDate.month,
                        convEventEndDate.day, convEventEndDate.hour,
                        convEventEndDate.minute))
        ids = account.calendar.find_items(
            start=startDate,
            end=endDate,
            categories=calendarCategory,
            shape=IdOnly,
        )

        # Get full selected items
        items = account.calendar.get_items(ids)

        # Delete selected items after they have been shown in calendarBot
        if deleteAfterwards:
            res = account.calendar.delete_items(ids)

    except Exception as e:
        return False, "Could not access event items in Outlook calendar due to following exception:\n {0} \n {1}".format(
            e.__doc__, e.message)

    return True, items
Exemplo n.º 19
0
    def test_recurring_item(self):
        # Create a recurring calendar item. Test that occurrence fields are correct on the master item

        # Create a master item with 4 daily occurrences from 8:00 to 10:00. 'start' and 'end' are values for the first
        # occurrence.
        start = EWSDateTime(2016,
                            1,
                            1,
                            8,
                            tzinfo=self.account.default_timezone)
        end = EWSDateTime(2016, 1, 1, 10, tzinfo=self.account.default_timezone)
        master_item = self.ITEM_CLASS(
            folder=self.test_folder,
            start=start,
            end=end,
            recurrence=Recurrence(pattern=DailyPattern(interval=1),
                                  start=start.date(),
                                  number=4),
            categories=self.categories,
        ).save()

        master_item.refresh()
        self.assertEqual(master_item.is_recurring, False)
        self.assertEqual(master_item.type, RECURRING_MASTER)
        self.assertIsInstance(master_item.first_occurrence, FirstOccurrence)
        self.assertEqual(master_item.first_occurrence.start, start)
        self.assertEqual(master_item.first_occurrence.end, end)
        self.assertIsInstance(master_item.last_occurrence, LastOccurrence)
        self.assertEqual(master_item.last_occurrence.start,
                         start + datetime.timedelta(days=3))
        self.assertEqual(master_item.last_occurrence.end,
                         end + datetime.timedelta(days=3))
        self.assertEqual(master_item.modified_occurrences, None)
        self.assertEqual(master_item.deleted_occurrences, None)

        # Test occurrences as full calendar items, unfolded from the master
        range_start, range_end = start, end + datetime.timedelta(days=3)
        unfolded = [
            i for i in self.test_folder.view(start=range_start, end=range_end)
            if self.match_cat(i)
        ]
        self.assertEqual(len(unfolded), 4)
        for item in unfolded:
            self.assertEqual(item.type, OCCURRENCE)
            self.assertEqual(item.is_recurring, True)

        first_occurrence = unfolded[0]
        self.assertEqual(first_occurrence.id, master_item.first_occurrence.id)
        self.assertEqual(first_occurrence.start,
                         master_item.first_occurrence.start)
        self.assertEqual(first_occurrence.end,
                         master_item.first_occurrence.end)

        second_occurrence = unfolded[1]
        self.assertEqual(second_occurrence.start,
                         master_item.start + datetime.timedelta(days=1))
        self.assertEqual(second_occurrence.end,
                         master_item.end + datetime.timedelta(days=1))

        third_occurrence = unfolded[2]
        self.assertEqual(third_occurrence.start,
                         master_item.start + datetime.timedelta(days=2))
        self.assertEqual(third_occurrence.end,
                         master_item.end + datetime.timedelta(days=2))

        last_occurrence = unfolded[3]
        self.assertEqual(last_occurrence.id, master_item.last_occurrence.id)
        self.assertEqual(last_occurrence.start,
                         master_item.last_occurrence.start)
        self.assertEqual(last_occurrence.end, master_item.last_occurrence.end)
Exemplo n.º 20
0
    def test_recurring_item(self):
        """Changes to an occurrence of a recurring task cause one-off tasks to be generated when the following updates
        are made:
        * The status property of a regenerating or nonregenerating recurrent task is set to Completed.
        * The start date or end date of a nonregenerating recurrent task is changed.
        """

        # Create a master non-regenerating item with 4 daily occurrences
        start = EWSDate(2016, 1, 1)
        recurrence = TaskRecurrence(pattern=DailyPattern(interval=1), start=start, number=4)
        nonregenerating_item = self.ITEM_CLASS(
            folder=self.test_folder,
            categories=self.categories,
            recurrence=recurrence,
        ).save()
        nonregenerating_item.refresh()
        master_item_id = nonregenerating_item.id
        self.assertEqual(nonregenerating_item.is_recurring, True)
        self.assertEqual(nonregenerating_item.change_count, 1)
        self.assertEqual(self.test_folder.filter(categories__contains=self.categories).count(), 1)

        # Change the start date. We should see a new task appear.
        master_item = self.get_item_by_id((master_item_id, None))
        master_item.recurrence.boundary.start = EWSDate(2016, 2, 1)
        occurrence_item = master_item.save()
        occurrence_item.refresh()
        self.assertEqual(occurrence_item.is_recurring, False)  # This is now the occurrence
        self.assertEqual(self.test_folder.filter(categories__contains=self.categories).count(), 2)

        # Check fields on the recurring item
        master_item = self.get_item_by_id((master_item_id, None))
        self.assertEqual(master_item.change_count, 2)
        self.assertEqual(master_item.due_date, EWSDate(2016, 1, 2))  # This is the next occurrence
        self.assertEqual(master_item.recurrence.boundary.number, 3)  # One less

        # Change the status to 'Completed'. We should see a new task appear.
        master_item.status = Task.COMPLETED
        occurrence_item = master_item.save()
        occurrence_item.refresh()
        self.assertEqual(occurrence_item.is_recurring, False)  # This is now the occurrence
        self.assertEqual(self.test_folder.filter(categories__contains=self.categories).count(), 3)

        # Check fields on the recurring item
        master_item = self.get_item_by_id((master_item_id, None))
        self.assertEqual(master_item.change_count, 3)
        self.assertEqual(master_item.due_date, EWSDate(2016, 2, 1))  # This is the next occurrence
        self.assertEqual(master_item.recurrence.boundary.number, 2)  # One less

        self.test_folder.filter(categories__contains=self.categories).delete()

        # Create a master regenerating item with 4 daily occurrences
        recurrence = TaskRecurrence(pattern=DailyRegeneration(interval=1), start=start, number=4)
        regenerating_item = self.ITEM_CLASS(
            folder=self.test_folder,
            categories=self.categories,
            recurrence=recurrence,
        ).save()
        regenerating_item.refresh()
        master_item_id = regenerating_item.id
        self.assertEqual(regenerating_item.is_recurring, True)
        self.assertEqual(regenerating_item.change_count, 1)
        self.assertEqual(self.test_folder.filter(categories__contains=self.categories).count(), 1)

        # Change the start date. We should *not* see a new task appear.
        master_item = self.get_item_by_id((master_item_id, None))
        master_item.recurrence.boundary.start = EWSDate(2016, 1, 2)
        occurrence_item = master_item.save()
        occurrence_item.refresh()
        self.assertEqual(occurrence_item.id, master_item.id)  # This is not an occurrence. No new task was created
        self.assertEqual(self.test_folder.filter(categories__contains=self.categories).count(), 1)

        # Change the status to 'Completed'. We should see a new task appear.
        master_item.status = Task.COMPLETED
        occurrence_item = master_item.save()
        occurrence_item.refresh()
        self.assertEqual(occurrence_item.is_recurring, False)  # This is now the occurrence
        self.assertEqual(self.test_folder.filter(categories__contains=self.categories).count(), 2)

        # Check fields on the recurring item
        master_item = self.get_item_by_id((master_item_id, None))
        self.assertEqual(master_item.change_count, 2)
        # The due date is the next occurrence after today
        tz = self.account.default_timezone
        self.assertEqual(master_item.due_date, EWSDateTime.now(tz).date() + datetime.timedelta(days=1))
        self.assertEqual(master_item.recurrence.boundary.number, 3)  # One less