18
21
from grackle.client import (
24
UnsupportedDisplayType,
29
def make_message(message_id, body='body', headers=None, hidden=False):
32
headers['Message-Id'] = message_id
34
'message_id': message_id,
36
'thread_id': message_id,
37
'date': headers.get('date', '2005-01-01'),
38
'subject': headers.get('subject', 'subject'),
39
'author': headers.get('author', 'author'),
42
'replies': headers.get('in-reply-to', None),
48
def make_mime_message(message_id, body='body', headers=None, hidden=False,
49
attachment_type=None):
50
message = MIMEMultipart()
51
message.attach(MIMEText(body))
52
if attachment_type is not None:
53
attachment = Message()
54
attachment.set_payload('attactment data.')
55
attachment['Content-Type'] = attachment_type
56
attachment['Content-Disposition'] = 'attachment; filename="file.ext"'
57
message.attach(attachment)
58
return make_message(message_id, message.get_payload(), headers, hidden)
24
61
def threaded_messages(messages):
28
65
for message in messages:
29
if message.get('in_reply_to') is None:
66
if message.get('replies') is None:
30
67
threads[message['message_id']] = [message]
33
70
pending.append(message)
34
71
for message in pending:
35
threads[message['in_reply_to']].append(message)
72
threads[message['replies']].append(message)
36
73
return threads.values()
70
111
messages.extend(thread)
72
113
messages.sort(key=lambda m: m[order])
114
display_type = parameters.get('display_type', 'all')
115
if display_type not in SUPPORTED_DISPLAY_TYPES:
116
raise UnsupportedDisplayType
117
if 'date_range' in parameters:
119
start_date, end_date = parameters['date_range'].split('..')
120
if not start_date or not end_date:
121
raise UnparsableDateRange
123
raise UnparsableDateRange
74
125
for message in messages:
75
if (not parameters['include_hidden']
76
and message.get('hidden', False)):
126
if (not parameters['include_hidden'] and message['hidden']):
79
128
if ('message_ids' in parameters
80
129
and message['message_id'] not in parameters['message_ids']):
131
if ('date_range' in parameters
132
and (message['date'] < start_date
133
or message['date'] > end_date)):
82
135
message = dict(message)
83
136
if 'headers' in parameters:
85
138
(k, v) for k, v in message['headers'].iteritems()
86
139
if k in parameters['headers'])
87
140
message['headers'] = headers
141
if display_type == 'headers-only':
143
elif display_type == 'text-only' and self.is_multipart(message):
145
part.get_payload() for part in message['body']
146
if part.get_content_type() == 'text/plain']
147
message['body'] = '\n\n'.join(text_parts)
148
elif display_type == 'all' and self.is_multipart(message):
149
parts = [str(part.get_payload()) for part in message['body']]
150
message['body'] = '\n\n'.join(parts)
88
151
max_body = parameters.get('max_body_length')
89
if max_body is not None:
152
if max_body is not None and display_type != 'headers-only':
90
153
message['body'] = message['body'][:max_body]
91
154
new_messages.append(message)
92
155
messages = new_messages
263
329
def test_get_messages_by_id(self):
264
330
client = GrackleClient('localhost', 8437)
265
with ForkedFake.from_client(client,
267
[{'message_id': 'foo'},
268
{'message_id': 'bar'}]}):
332
'baz': [make_message('foo'), make_message('bar')]}
333
with ForkedFakeService.from_client(client, archive):
269
334
response = client.get_messages('baz', message_ids=['foo'])
270
335
message, = response['messages']
271
336
self.assertEqual('foo', message['message_id'])
273
338
def test_get_messages_batching(self):
274
339
client = GrackleClient('localhost', 8438)
275
with ForkedFake.from_client(client,
277
[{'message_id': 'foo'},
278
{'message_id': 'bar'}]}):
340
archive = {'baz': [make_message('foo'), make_message('bar')]}
341
with ForkedFakeService.from_client(client, archive):
279
342
response = client.get_messages('baz', limit=1)
280
343
self.assertEqual(1, len(response['messages']))
281
344
messages = response['messages']
305
371
self.get_messages_member_order_test('subject')
307
373
def test_get_messages_thread_subject_order(self):
376
make_message('bar', headers={'subject': 'y'}),
377
make_message('qux', headers={'subject': 'z'}),
378
make_message('foo', headers={'subject': 'x',
379
'in-reply-to': 'qux'}),
308
381
client = GrackleClient('localhost', 8439)
309
with ForkedFake.from_client(client, {'baz': [
310
{'message_id': 'bar', 'subject': 'y'},
311
{'message_id': 'qux', 'subject': 'z'},
312
{'message_id': 'foo', 'subject': 'x', 'in_reply_to': 'qux'},
382
with ForkedFakeService.from_client(client, archive):
314
383
response = client.get_messages('baz')
315
384
self.assertIDOrder(['bar', 'qux', 'foo'], response['messages'])
316
385
response = client.get_messages('baz', order='subject')
321
390
def test_get_messages_thread_oldest_order(self):
322
391
client = GrackleClient('localhost', 8439)
323
with ForkedFake.from_client(client, {'baz': [
324
{'message_id': 'bar', 'date': 'x'},
325
{'message_id': 'qux', 'date': 'z'},
326
{'message_id': 'foo', 'date': 'y', 'in_reply_to': 'qux'},
394
make_message('bar', headers={'date': 'x'}),
395
make_message('qux', headers={'date': 'z'}),
396
make_message('foo', headers={'date': 'y',
397
'in-reply-to': 'qux'}),
399
with ForkedFakeService.from_client(client, archive):
328
400
response = client.get_messages('baz')
329
401
self.assertIDOrder(['bar', 'qux', 'foo'], response['messages'])
330
402
response = client.get_messages('baz', order='date')
335
407
def test_get_messages_thread_newest_order(self):
336
408
client = GrackleClient('localhost', 8439)
337
with ForkedFake.from_client(client, {'baz': [
338
{'message_id': 'bar', 'date': 'x'},
339
{'message_id': 'qux', 'date': 'w'},
340
{'message_id': 'foo', 'date': 'y', 'in_reply_to': 'bar'},
341
{'message_id': 'baz', 'date': 'z', 'in_reply_to': 'qux'},
411
make_message('bar', headers={'date': 'x'}),
412
make_message('qux', headers={'date': 'w'}),
413
make_message('foo', headers={'date': 'y',
414
'in-reply-to': 'bar'}),
415
make_message('baz', headers={'date': 'z',
416
'in-reply-to': 'qux'}),
418
with ForkedFakeService.from_client(client, archive):
343
419
response = client.get_messages('baz', order='date')
344
420
self.assertIDOrder(
345
421
['qux', 'bar', 'foo', 'baz'], response['messages'])
350
426
def test_get_messages_unsupported_order(self):
351
427
client = GrackleClient('localhost', 8439)
352
with ForkedFake.from_client(client,
353
{'baz': [{'message_id': 'foo', 'date': '2011-03-25'},
354
{'message_id': 'bar', 'date': '2011-03-24'}]}):
430
make_message('foo', headers={'date': '2011-03-25'}),
431
make_message('foo', headers={'date': '2011-03-24'}),
433
with ForkedFakeService.from_client(client, archive):
355
434
with ExpectedException(UnsupportedOrder, ''):
356
435
client.get_messages('baz', order='nonsense')
358
437
def test_get_messages_headers_no_headers(self):
359
438
client = GrackleClient('localhost', 8440)
360
with ForkedFake.from_client(client,
362
{'message_id': 'foo'}
439
archive = {'baz': [make_message('foo')]}
440
with ForkedFakeService.from_client(client, archive):
364
441
response = client.get_messages('baz', headers=[
365
442
'Subject', 'Date', 'X-Launchpad-Message-Rationale'])
366
443
first_message = response['messages'][0]
394
470
def test_get_messages_max_body_length(self):
395
471
client = GrackleClient('localhost', 8443)
396
with ForkedFake.from_client(client,
398
{'message_id': 'foo', 'body': u'abcdefghi'}
472
archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
473
with ForkedFakeService.from_client(client, archive):
400
474
response = client.get_messages('baz', max_body_length=3)
401
475
first_message = response['messages'][0]
402
476
self.assertEqual('abc', first_message['body'])
404
478
def test_include_hidden(self):
405
479
client = GrackleClient('localhost', 8444)
406
with ForkedFake.from_client(client,
408
{'message_id': 'foo', 'hidden': True},
409
{'message_id': 'bar', 'hidden': False}
482
make_message('foo', hidden=True),
483
make_message('bar', hidden=False),
485
with ForkedFakeService.from_client(client, archive):
411
486
response = client.get_messages('baz', include_hidden=True)
412
487
self.assertMessageIDs(['bar', 'foo'], response['messages'])
413
488
response = client.get_messages('baz', include_hidden=False)
414
489
self.assertMessageIDs(['bar'], response['messages'])
491
def test_display_type_unknown_value(self):
492
client = GrackleClient('localhost', 8445)
493
archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
494
with ForkedFakeService.from_client(client, archive):
495
with ExpectedException(UnsupportedDisplayType, ''):
496
client.get_messages('baz', display_type='unknown')
498
def test_display_type_headers_only(self):
499
client = GrackleClient('localhost', 8446)
502
make_message('foo', body=u'abcdefghi',
503
headers={'From': 'me', 'To': 'you'})]}
504
with ForkedFakeService.from_client(client, archive):
505
response = client.get_messages('baz', display_type='headers-only')
506
first_message = response['messages'][0]
507
self.assertEqual('foo', first_message['message_id'])
509
{'From': 'me', 'Message-Id': 'foo', 'To': 'you'},
510
first_message['headers'])
511
self.assertNotIn('body', first_message)
513
def test_display_type_text_only(self):
514
client = GrackleClient('localhost', 8446)
519
headers={'From': 'me', 'To': 'you'},
520
attachment_type='text/x-diff')]}
521
with ForkedFakeService.from_client(client, archive):
522
response = client.get_messages('baz', display_type='text-only')
523
first_message = response['messages'][0]
524
self.assertEqual('foo', first_message['message_id'])
525
self.assertEqual('me', first_message['headers']['From'])
526
self.assertEqual('you', first_message['headers']['To'])
527
self.assertEqual('abcdefghi', first_message['body'])
529
def test_display_type_all(self):
530
client = GrackleClient('localhost', 8447)
535
headers={'From': 'me', 'To': 'you'},
536
attachment_type='text/x-diff')]}
537
with ForkedFakeService.from_client(client, archive):
538
response = client.get_messages('baz', display_type='all')
539
first_message = response['messages'][0]
540
self.assertEqual('foo', first_message['message_id'])
541
self.assertEqual('me', first_message['headers']['From'])
542
self.assertEqual('you', first_message['headers']['To'])
544
'abcdefghi\n\nattactment data.', first_message['body'])
546
def test_date_range(self):
547
client = GrackleClient('localhost', 8448)
551
'foo', 'abcdefghi', headers={'date': '2011-12-31'}),
553
'bar', 'abcdefghi', headers={'date': '2012-01-01'}),
555
'qux', 'abcdefghi', headers={'date': '2012-01-15'}),
557
'naf', 'abcdefghi', headers={'date': '2012-01-31'}),
559
'doh', 'abcdefghi', headers={'date': '2012-02-01'}),
561
with ForkedFakeService.from_client(client, archive):
562
response = client.get_messages(
563
'baz', date_range='2012-01-01..2012-01-31')
564
ids = sorted(m['message_id'] for m in response['messages'])
565
self.assertEqual(['bar', 'naf', 'qux'], ids)
567
def test_date_range_unparsabledaterange(self):
568
client = GrackleClient('localhost', 8448)
569
archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
570
with ForkedFakeService.from_client(client, archive):
571
with ExpectedException(UnparsableDateRange, ''):
572
client.get_messages('baz', date_range='2012-01-01')
574
def test_date_range_unparsabledaterange_missing_part(self):
575
client = GrackleClient('localhost', 8448)
576
archive = {'baz': [make_message('foo', body=u'abcdefghi')]}
577
with ForkedFakeService.from_client(client, archive):
578
with ExpectedException(UnparsableDateRange, ''):
579
client.get_messages('baz', date_range='2012-01-01..')