Пример #1
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))
Пример #2
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))
Пример #3
0
    def test_finditems(self):
        now = UTC_NOW()

        # Test argument types
        item = self.get_test_item()
        ids = self.test_folder.bulk_create(items=[item])
        # No arguments. There may be leftover items in the folder, so just make sure there's at least one.
        self.assertGreaterEqual(self.test_folder.filter().count(), 1)
        # Q object
        self.assertEqual(
            self.test_folder.filter(Q(subject=item.subject)).count(), 1)
        # Multiple Q objects
        self.assertEqual(
            self.test_folder.filter(
                Q(subject=item.subject),
                ~Q(subject=item.subject[:-3] + 'XXX')).count(), 1)
        # Multiple Q object and kwargs
        self.assertEqual(
            self.test_folder.filter(
                Q(subject=item.subject),
                categories__contains=item.categories).count(), 1)
        self.bulk_delete(ids)

        # Test categories which are handled specially - only '__contains' and '__in' lookups are supported
        item = self.get_test_item(categories=['TestA', 'TestB'])
        ids = self.test_folder.bulk_create(items=[item])
        common_qs = self.test_folder.filter(
            subject=item.subject)  # Guard against other simultaneous runs
        self.assertEqual(
            common_qs.filter(
                categories__contains='ci6xahH1').count(),  # Plain string
            0)
        self.assertEqual(
            common_qs.filter(categories__contains=['ci6xahH1']).count(
            ),  # Same, but as list
            0)
        self.assertEqual(
            common_qs.filter(categories__contains=['TestA', 'TestC']).count(
            ),  # One wrong category
            0)
        self.assertEqual(
            common_qs.filter(categories__contains=['TESTA']).count(
            ),  # Test case insensitivity
            1)
        self.assertEqual(
            common_qs.filter(categories__contains=['testa']).count(
            ),  # Test case insensitivity
            1)
        self.assertEqual(
            common_qs.filter(
                categories__contains=['TestA']).count(),  # Partial
            1)
        self.assertEqual(
            common_qs.filter(
                categories__contains=item.categories).count(),  # Exact match
            1)
        with self.assertRaises(ValueError):
            common_qs.filter(categories__in='ci6xahH1').count(
            )  # Plain string is not supported
        self.assertEqual(
            common_qs.filter(
                categories__in=['ci6xahH1']).count(),  # Same, but as list
            0)
        self.assertEqual(
            common_qs.filter(categories__in=['TestA', 'TestC'
                                             ]).count(),  # One wrong category
            1)
        self.assertEqual(
            common_qs.filter(categories__in=['TestA']).count(),  # Partial
            1)
        self.assertEqual(
            common_qs.filter(
                categories__in=item.categories).count(),  # Exact match
            1)
        self.bulk_delete(ids)

        common_qs = self.test_folder.filter(
            categories__contains=self.categories)
        one_hour = datetime.timedelta(hours=1)
        two_hours = datetime.timedelta(hours=2)
        # Test 'exists'
        ids = self.test_folder.bulk_create(items=[self.get_test_item()])
        self.assertEqual(
            common_qs.filter(datetime_created__exists=True).count(), 1)
        self.assertEqual(
            common_qs.filter(datetime_created__exists=False).count(), 0)
        self.bulk_delete(ids)

        # Test 'range'
        ids = self.test_folder.bulk_create(items=[self.get_test_item()])
        self.assertEqual(
            common_qs.filter(datetime_created__range=(now + one_hour, now +
                                                      two_hours)).count(), 0)
        self.assertEqual(
            common_qs.filter(datetime_created__range=(now - one_hour,
                                                      now + one_hour)).count(),
            1)
        self.bulk_delete(ids)

        # Test '>'
        ids = self.test_folder.bulk_create(items=[self.get_test_item()])
        self.assertEqual(
            common_qs.filter(datetime_created__gt=now + one_hour).count(), 0)
        self.assertEqual(
            common_qs.filter(datetime_created__gt=now - one_hour).count(), 1)
        self.bulk_delete(ids)

        # Test '>='
        ids = self.test_folder.bulk_create(items=[self.get_test_item()])
        self.assertEqual(
            common_qs.filter(datetime_created__gte=now + one_hour).count(), 0)
        self.assertEqual(
            common_qs.filter(datetime_created__gte=now - one_hour).count(), 1)
        self.bulk_delete(ids)

        # Test '<'
        ids = self.test_folder.bulk_create(items=[self.get_test_item()])
        self.assertEqual(
            common_qs.filter(datetime_created__lt=now - one_hour).count(), 0)
        self.assertEqual(
            common_qs.filter(datetime_created__lt=now + one_hour).count(), 1)
        self.bulk_delete(ids)

        # Test '<='
        ids = self.test_folder.bulk_create(items=[self.get_test_item()])
        self.assertEqual(
            common_qs.filter(datetime_created__lte=now - one_hour).count(), 0)
        self.assertEqual(
            common_qs.filter(datetime_created__lte=now + one_hour).count(), 1)
        self.bulk_delete(ids)

        # Test '='
        item = self.get_test_item()
        ids = self.test_folder.bulk_create(items=[item])
        self.assertEqual(
            common_qs.filter(subject=item.subject[:-3] + 'XXX').count(), 0)
        self.assertEqual(common_qs.filter(subject=item.subject).count(), 1)
        self.bulk_delete(ids)

        # Test '!='
        item = self.get_test_item()
        ids = self.test_folder.bulk_create(items=[item])
        self.assertEqual(
            common_qs.filter(subject__not=item.subject).count(), 0)
        self.assertEqual(
            common_qs.filter(subject__not=item.subject[:-3] + 'XXX').count(),
            1)
        self.bulk_delete(ids)

        # Test 'exact'
        item = self.get_test_item()
        item.subject = 'aA' + item.subject[2:]
        ids = self.test_folder.bulk_create(items=[item])
        self.assertEqual(
            common_qs.filter(subject__exact=item.subject[:-3] + 'XXX').count(),
            0)
        self.assertEqual(
            common_qs.filter(subject__exact=item.subject.lower()).count(), 0)
        self.assertEqual(
            common_qs.filter(subject__exact=item.subject.upper()).count(), 0)
        self.assertEqual(
            common_qs.filter(subject__exact=item.subject).count(), 1)
        self.bulk_delete(ids)

        # Test 'iexact'
        item = self.get_test_item()
        item.subject = 'aA' + item.subject[2:]
        ids = self.test_folder.bulk_create(items=[item])
        self.assertEqual(
            common_qs.filter(subject__iexact=item.subject[:-3] +
                             'XXX').count(), 0)
        self.assertIn(
            common_qs.filter(subject__iexact=item.subject.lower()).count(),
            (0, 1)  # iexact search is broken on some EWS versions
        )
        self.assertIn(
            common_qs.filter(subject__iexact=item.subject.upper()).count(),
            (0, 1)  # iexact search is broken on some EWS versions
        )
        self.assertEqual(
            common_qs.filter(subject__iexact=item.subject).count(), 1)
        self.bulk_delete(ids)

        # Test 'contains'
        item = self.get_test_item()
        item.subject = item.subject[2:8] + 'aA' + item.subject[8:]
        ids = self.test_folder.bulk_create(items=[item])
        self.assertEqual(
            common_qs.filter(subject__contains=item.subject[2:14] +
                             'XXX').count(), 0)
        self.assertEqual(
            common_qs.filter(
                subject__contains=item.subject[2:14].lower()).count(), 0)
        self.assertEqual(
            common_qs.filter(
                subject__contains=item.subject[2:14].upper()).count(), 0)
        self.assertEqual(
            common_qs.filter(subject__contains=item.subject[2:14]).count(), 1)
        self.bulk_delete(ids)

        # Test 'icontains'
        item = self.get_test_item()
        item.subject = item.subject[2:8] + 'aA' + item.subject[8:]
        ids = self.test_folder.bulk_create(items=[item])
        self.assertEqual(
            common_qs.filter(subject__icontains=item.subject[2:14] +
                             'XXX').count(), 0)
        self.assertIn(
            common_qs.filter(
                subject__icontains=item.subject[2:14].lower()).count(),
            (0, 1)  # icontains search is broken on some EWS versions
        )
        self.assertIn(
            common_qs.filter(
                subject__icontains=item.subject[2:14].upper()).count(),
            (0, 1)  # icontains search is broken on some EWS versions
        )
        self.assertEqual(
            common_qs.filter(subject__icontains=item.subject[2:14]).count(), 1)
        self.bulk_delete(ids)

        # Test 'startswith'
        item = self.get_test_item()
        item.subject = 'aA' + item.subject[2:]
        ids = self.test_folder.bulk_create(items=[item])
        self.assertEqual(
            common_qs.filter(subject__startswith='XXX' +
                             item.subject[:12]).count(), 0)
        self.assertEqual(
            common_qs.filter(
                subject__startswith=item.subject[:12].lower()).count(), 0)
        self.assertEqual(
            common_qs.filter(
                subject__startswith=item.subject[:12].upper()).count(), 0)
        self.assertEqual(
            common_qs.filter(subject__startswith=item.subject[:12]).count(), 1)
        self.bulk_delete(ids)

        # Test 'istartswith'
        item = self.get_test_item()
        item.subject = 'aA' + item.subject[2:]
        ids = self.test_folder.bulk_create(items=[item])
        self.assertEqual(
            common_qs.filter(subject__istartswith='XXX' +
                             item.subject[:12]).count(), 0)
        self.assertIn(
            common_qs.filter(
                subject__istartswith=item.subject[:12].lower()).count(),
            (0, 1)  # istartswith search is broken on some EWS versions
        )
        self.assertIn(
            common_qs.filter(
                subject__istartswith=item.subject[:12].upper()).count(),
            (0, 1)  # istartswith search is broken on some EWS versions
        )
        self.assertEqual(
            common_qs.filter(subject__istartswith=item.subject[:12]).count(),
            1)
        self.bulk_delete(ids)
Пример #4
0
# Use notify-send for email notifications and zenity for calendar notifications
notify = sh.Command('/usr/bin/notify-send')
zenity = sh.Command('/usr/bin/zenity')

# Get the local timezone
timedatectl = sh.Command('/usr/bin/timedatectl')
for l in timedatectl():
    if 'Timezone' in l:
        tz_name = l.split()[1]
        break
else:
    raise ValueError('Timezone not found')
tz = EWSTimeZone.timezone(tz_name)

sleep = int(sys.argv[1])  # 1st arg to this script is the number of seconds to look back in the inbox
now = UTC_NOW()
emails_since = now - timedelta(seconds=sleep)
cal_items_before = now + timedelta(seconds=sleep * 4)  # Longer notice of upcoming appointments than new emails
username, _, password = netrc().authenticators('office365')
c = Credentials(username, password, is_service_account=False)
a = Account(primary_smtp_address=c.username, credentials=c, access_type=DELEGATE, autodiscover=True, verify_ssl=False)

for msg in a.calendar.view(start=now, end=cal_items_before)\
        .only('start', 'end', 'subject', 'location')\
        .order_by('start', 'end'):
    if msg.start < now:
        continue
    minutes_to_appointment = int((msg.start - now).total_seconds() / 60)
    subj = 'You have a meeting in %s minutes' % minutes_to_appointment
    body = '%s-%s: %s\n%s' % (
        msg.start.astimezone(tz).strftime('%H:%M'),  
Пример #5
0
 def get_random_update_kwargs(self, item, insert_kwargs):
     update_kwargs = {}
     now = UTC_NOW()
     for f in self.ITEM_CLASS.FIELDS:
         if not f.supports_version(self.account.version):
             # Cannot be used with this EWS version
             continue
         if self.ITEM_CLASS == CalendarItem and f in CalendarItem.timezone_fields(
         ):
             # Timezone fields will (and must) be populated automatically from the timestamp
             continue
         if f.is_read_only:
             # These cannot be changed
             continue
         if not item.is_draft and f.is_read_only_after_send:
             # These cannot be changed when the item is no longer a draft
             continue
         if f.name == 'message_id' and f.is_read_only_after_send:
             # Cannot be updated, regardless of draft status
             continue
         if f.name == 'attachments':
             # Testing attachments is heavy. Leave this to specific tests
             update_kwargs[f.name] = []
             continue
         if f.name == 'resources':
             # The test server doesn't have any resources
             update_kwargs[f.name] = []
             continue
         if isinstance(f, AttachmentField):
             # Attachments are handled separately
             continue
         if f.name == 'start':
             start = get_random_date(start_date=insert_kwargs['end'].date())
             update_kwargs[f.name], update_kwargs['end'] = \
                 get_random_datetime_range(start_date=start, end_date=start, tz=self.account.default_timezone)
             update_kwargs['recurrence'] = self.random_val(
                 self.ITEM_CLASS.get_field_by_fieldname('recurrence'))
             update_kwargs['recurrence'].boundary.start = update_kwargs[
                 f.name].date()
             continue
         if f.name == 'end':
             continue
         if f.name == 'recurrence':
             continue
         if f.name == 'due_date':
             # start_date must be before due_date, and before complete_date which must be in the past
             update_kwargs['start_date'], update_kwargs[f.name] = \
                 get_random_datetime_range(end_date=now.date(), tz=self.account.default_timezone)
             continue
         if f.name == 'start_date':
             continue
         if f.name == 'status':
             # Update task to a completed state. complete_date must be a date in the past, and < than start_date
             update_kwargs[f.name] = Task.COMPLETED
             update_kwargs['percent_complete'] = Decimal(100)
             continue
         if f.name == 'percent_complete':
             continue
         if f.name == 'reminder_is_set':
             if self.ITEM_CLASS == Task:
                 # Task type doesn't allow updating 'reminder_is_set' to True
                 update_kwargs[f.name] = False
             else:
                 update_kwargs[f.name] = not insert_kwargs[f.name]
             continue
         if isinstance(f, BooleanField):
             update_kwargs[f.name] = not insert_kwargs[f.name]
             continue
         if f.value_cls in (Mailbox, Attendee):
             if insert_kwargs[f.name] is None:
                 update_kwargs[f.name] = self.random_val(f)
             else:
                 update_kwargs[f.name] = None
             continue
         update_kwargs[f.name] = self.random_val(f)
     if self.ITEM_CLASS == CalendarItem:
         # EWS always sets due date to 'start'
         update_kwargs['reminder_due_by'] = update_kwargs['start']
     if update_kwargs.get('is_all_day', False):
         # For is_all_day items, EWS will remove the time part of start and end values
         update_kwargs['start'] = update_kwargs['start'].date()
         update_kwargs['end'] = (update_kwargs['end'] +
                                 datetime.timedelta(days=1)).date()
     return update_kwargs