Skip to content

Commit 5a4c23e

Browse files
committed
Merge with trunk
- Legacy-Id: 3676
2 parents 70ad270 + e359684 commit 5a4c23e

224 files changed

Lines changed: 21124 additions & 862 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

django/contrib/admin/templatetags/admin_list.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,10 @@ def result_headers(cl):
110110
# It is a non-field, but perhaps one that is sortable
111111
admin_order_field = getattr(attr, "admin_order_field", None)
112112
if not admin_order_field:
113-
yield {"text": header}
113+
yield {
114+
"text": header,
115+
"class_attrib": ""
116+
}
114117
continue
115118

116119
# So this _is_ a sortable non-field. Go to the yield

ietf/announcements/admin.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#coding: utf-8
22
from django.contrib import admin
3+
from django.conf import settings
34
from ietf.announcements.models import *
45

56
class AnnouncedFromAdmin(admin.ModelAdmin):
@@ -21,3 +22,22 @@ class ScheduledAnnouncementAdmin(admin.ModelAdmin):
2122
pass
2223
admin.site.register(ScheduledAnnouncement, ScheduledAnnouncementAdmin)
2324

25+
26+
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
27+
class MessageAdmin(admin.ModelAdmin):
28+
list_display = ["time", "by", "subject", "groups"]
29+
search_fields = ["body"]
30+
raw_id_fields = ["by"]
31+
32+
def groups(self, instance):
33+
return ", ".join(g.acronym for g in related_groups.all())
34+
35+
admin.site.register(Message, MessageAdmin)
36+
37+
class SendQueueAdmin(admin.ModelAdmin):
38+
list_display = ["time", "by", "message", "send_at", "sent_at"]
39+
list_filter = ["time", "send_at", "sent_at"]
40+
search_fields = ["message__body"]
41+
raw_id_fields = ["by"]
42+
43+
admin.site.register(SendQueue, SendQueueAdmin)

ietf/announcements/models.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Copyright The IETF Trust 2007, All Rights Reserved
22

33
from django.db import models
4+
from django.conf import settings
45
from ietf.idtracker.models import PersonOrOrgInfo, ChairsHistory
56
#from django.contrib.auth.models import Permission
67

@@ -87,3 +88,43 @@ class Meta:
8788
db_table = 'scheduled_announcements'
8889

8990

91+
if settings.USE_DB_REDESIGN_PROXY_CLASSES or hasattr(settings, "IMPORTING_FROM_OLD_SCHEMA"):
92+
import datetime
93+
94+
from person.models import Email, Person
95+
from group.models import Group
96+
97+
class Message(models.Model):
98+
time = models.DateTimeField(default=datetime.datetime.now)
99+
by = models.ForeignKey(Person)
100+
101+
subject = models.CharField(max_length=255)
102+
frm = models.CharField(max_length=255)
103+
to = models.CharField(max_length=1024)
104+
cc = models.CharField(max_length=1024, blank=True)
105+
bcc = models.CharField(max_length=255, blank=True)
106+
reply_to = models.CharField(max_length=255, blank=True)
107+
body = models.TextField()
108+
content_type = models.CharField(max_length=255, blank=True)
109+
110+
related_groups = models.ManyToManyField(Group, blank=True)
111+
112+
class Meta:
113+
ordering = ['time']
114+
115+
def __unicode__(self):
116+
return "'%s' %s -> %s" % (self.subject, self.frm, self.to)
117+
118+
class SendQueue(models.Model):
119+
time = models.DateTimeField(default=datetime.datetime.now)
120+
by = models.ForeignKey(Person)
121+
122+
message = models.ForeignKey(Message)
123+
124+
send_at = models.DateTimeField(blank=True, null=True)
125+
sent_at = models.DateTimeField(blank=True, null=True)
126+
127+
note = models.TextField(blank=True)
128+
129+
class Meta:
130+
ordering = ['time']

ietf/announcements/send_scheduled.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import re, datetime, email
22

3+
from django.conf import settings
4+
35
from ietf.utils.mail import send_mail_text, send_mail_mime
46

57
first_dot_on_line_re = re.compile(r'^\.', re.MULTILINE)
@@ -8,7 +10,6 @@ def send_scheduled_announcement(announcement):
810
# for some reason, the old Perl code base substituted away . on line starts
911
body = first_dot_on_line_re.sub("", announcement.body)
1012

11-
announcement.content_type
1213
extra = {}
1314
if announcement.replyto:
1415
extra['Reply-To'] = announcement.replyto
@@ -33,3 +34,35 @@ def send_scheduled_announcement(announcement):
3334
announcement.actual_sent_time = str(now.time())
3435
announcement.mail_sent = True
3536
announcement.save()
37+
38+
39+
def send_scheduled_announcementREDESIGN(send_queue):
40+
message = send_queue.message
41+
42+
# for some reason, the old Perl code base substituted away . on line starts
43+
body = first_dot_on_line_re.sub("", message.body)
44+
45+
extra = {}
46+
if message.reply_to:
47+
extra['Reply-To'] = message.reply_to
48+
49+
# announcement.content_type can contain a case-sensitive parts separator,
50+
# so we need to keep it as is, not lowercased, but we want a lowercased
51+
# version for the coming comparisons.
52+
content_type_lowercase = message.content_type.lower()
53+
if not content_type_lowercase or 'text/plain' in content_type_lowercase:
54+
send_mail_text(None, message.to, message.frm, message.subject,
55+
body, cc=message.cc, bcc=message.bcc)
56+
elif 'multipart' in content_type_lowercase:
57+
# make body a real message so we can parse it
58+
body = ("MIME-Version: 1.0\r\nContent-Type: %s\r\n" % message.content_type) + body
59+
60+
msg = email.message_from_string(body.encode("utf-8"))
61+
send_mail_mime(None, message.to, message.frm, message.subject,
62+
msg, cc=message.cc, bcc=message.bcc)
63+
64+
send_queue.sent_at = datetime.datetime.now()
65+
send_queue.save()
66+
67+
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
68+
send_scheduled_announcement = send_scheduled_announcementREDESIGN

ietf/announcements/tests.py

Lines changed: 84 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
import datetime
2+
3+
from django.conf import settings
14
import django.test
25

36
from ietf.utils.test_utils import SimpleUrlTestCase, canonicalize_sitemap
4-
from ietf.utils.test_runner import mail_outbox
7+
from ietf.utils.test_data import make_test_data
8+
from ietf.utils.mail import outbox
59

610
from ietf.announcements.models import ScheduledAnnouncement
711

@@ -27,13 +31,13 @@ def test_send_plain_announcement(self):
2731
content_type="",
2832
)
2933

30-
mailbox_before = len(mail_outbox)
34+
mailbox_before = len(outbox)
3135

3236
from ietf.announcements.send_scheduled import send_scheduled_announcement
3337
send_scheduled_announcement(a)
3438

35-
self.assertEquals(len(mail_outbox), mailbox_before + 1)
36-
self.assertTrue("This is a test" in mail_outbox[-1]["Subject"])
39+
self.assertEquals(len(outbox), mailbox_before + 1)
40+
self.assertTrue("This is a test" in outbox[-1]["Subject"])
3741
self.assertTrue(ScheduledAnnouncement.objects.get(id=a.id).mail_sent)
3842

3943
def test_send_mime_announcement(self):
@@ -48,12 +52,84 @@ def test_send_mime_announcement(self):
4852
content_type='Multipart/Mixed; Boundary="NextPart"',
4953
)
5054

51-
mailbox_before = len(mail_outbox)
55+
mailbox_before = len(outbox)
5256

5357
from ietf.announcements.send_scheduled import send_scheduled_announcement
5458
send_scheduled_announcement(a)
5559

56-
self.assertEquals(len(mail_outbox), mailbox_before + 1)
57-
self.assertTrue("This is a test" in mail_outbox[-1]["Subject"])
58-
self.assertTrue("--NextPart" in mail_outbox[-1].as_string())
60+
self.assertEquals(len(outbox), mailbox_before + 1)
61+
self.assertTrue("This is a test" in outbox[-1]["Subject"])
62+
self.assertTrue("--NextPart" in outbox[-1].as_string())
5963
self.assertTrue(ScheduledAnnouncement.objects.get(id=a.id).mail_sent)
64+
65+
66+
class SendScheduledAnnouncementsTestCaseREDESIGN(django.test.TestCase):
67+
fixtures = ["names"]
68+
69+
def test_send_plain_announcement(self):
70+
from ietf.announcements.models import Message, SendQueue
71+
from redesign.person.models import Person
72+
73+
make_test_data()
74+
75+
msg = Message.objects.create(
76+
by=Person.objects.get(name="(System)"),
77+
subject="This is a test",
78+
to="test@example.com",
79+
frm="testmonkey@example.com",
80+
cc="cc.a@example.com, cc.b@example.com",
81+
bcc="bcc@example.com",
82+
body="Hello World!",
83+
content_type="",
84+
)
85+
86+
q = SendQueue.objects.create(
87+
by=Person.objects.get(name="(System)"),
88+
message=msg,
89+
send_at=datetime.datetime.now() + datetime.timedelta(hours=12)
90+
)
91+
92+
mailbox_before = len(outbox)
93+
94+
from ietf.announcements.send_scheduled import send_scheduled_announcement
95+
send_scheduled_announcement(q)
96+
97+
self.assertEquals(len(outbox), mailbox_before + 1)
98+
self.assertTrue("This is a test" in outbox[-1]["Subject"])
99+
self.assertTrue(SendQueue.objects.get(id=q.id).sent_at)
100+
101+
def test_send_mime_announcement(self):
102+
from ietf.announcements.models import Message, SendQueue
103+
from redesign.person.models import Person
104+
105+
make_test_data()
106+
107+
msg = Message.objects.create(
108+
by=Person.objects.get(name="(System)"),
109+
subject="This is a test",
110+
to="test@example.com",
111+
frm="testmonkey@example.com",
112+
cc="cc.a@example.com, cc.b@example.com",
113+
bcc="bcc@example.com",
114+
body='--NextPart\r\n\r\nA New Internet-Draft is available from the on-line Internet-Drafts directories.\r\n--NextPart\r\nContent-Type: Message/External-body;\r\n\tname="draft-huang-behave-bih-01.txt";\r\n\tsite="ftp.ietf.org";\r\n\taccess-type="anon-ftp";\r\n\tdirectory="internet-drafts"\r\n\r\nContent-Type: text/plain\r\nContent-ID: <2010-07-30001541.I-D@ietf.org>\r\n\r\n--NextPart--',
115+
content_type='Multipart/Mixed; Boundary="NextPart"',
116+
)
117+
118+
q = SendQueue.objects.create(
119+
by=Person.objects.get(name="(System)"),
120+
message=msg,
121+
send_at=datetime.datetime.now() + datetime.timedelta(hours=12)
122+
)
123+
124+
mailbox_before = len(outbox)
125+
126+
from ietf.announcements.send_scheduled import send_scheduled_announcement
127+
send_scheduled_announcement(q)
128+
129+
self.assertEquals(len(outbox), mailbox_before + 1)
130+
self.assertTrue("This is a test" in outbox[-1]["Subject"])
131+
self.assertTrue("--NextPart" in outbox[-1].as_string())
132+
self.assertTrue(SendQueue.objects.get(id=q.id).sent_at)
133+
134+
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
135+
SendScheduledAnnouncementsTestCase = SendScheduledAnnouncementsTestCaseREDESIGN

ietf/announcements/urls.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
from django.conf.urls.defaults import patterns
44
from ietf.announcements.models import Announcement
55

6+
from django.conf import settings
7+
68
nomcom_dict = {
79
'queryset': Announcement.objects.all().filter(nomcom=True)
8-
}
10+
}
911

1012
urlpatterns = patterns('',
1113
# (r'^nomcom/$', 'django.views.generic.simple.redirect_to', {'url': 'http://www.ietf.org/nomcom/index.html'} ),
1214
(r'^nomcom/$', 'ietf.announcements.views.nomcom'),
13-
(r'^nomcom/(?P<object_id>\d+)/$', 'django.views.generic.list_detail.object_detail', nomcom_dict)
15+
(r'^nomcom/(?P<object_id>\d+)/$', 'ietf.announcements.views.message_detail' if settings.USE_DB_REDESIGN_PROXY_CLASSES else 'django.views.generic.list_detail.object_detail', nomcom_dict)
1416
)

ietf/announcements/views.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
# Copyright The IETF Trust 2007, All Rights Reserved
22

33
from django.views.generic.simple import direct_to_template
4+
from django.shortcuts import get_object_or_404
5+
from django.conf import settings
6+
from django.db.models import Q
7+
8+
import re
49

510
from ietf.idtracker.models import ChairsHistory
611
from ietf.idtracker.models import Role
@@ -29,3 +34,56 @@ def nomcom(request):
2934
{ 'curr_chair' : curr_chair,
3035
'regimes' : regimes })
3136

37+
def nomcomREDESIGN(request):
38+
from group.models import Group
39+
from ietf.announcements.models import Message
40+
41+
address_re = re.compile("<.*>")
42+
43+
nomcoms = list(Group.objects.filter(acronym__startswith="nomcom").exclude(name="nomcom"))
44+
45+
regimes = []
46+
47+
for n in nomcoms:
48+
e = n.latest_event(type="started")
49+
n.start_year = e.time.year if e else 0
50+
if n.start_year <= 2003:
51+
continue
52+
e = n.latest_event(type="concluded")
53+
n.end_year = e.time.year if e else ""
54+
55+
chair = n.role_set.get(name="chair").person
56+
announcements = Message.objects.filter(related_groups=n).order_by('-time')
57+
for a in announcements:
58+
a.to_name = address_re.sub("", a.to)
59+
60+
regimes.append(dict(chair=chair,
61+
announcements=announcements,
62+
group=n))
63+
64+
regimes.sort(key=lambda x: x["group"].start_year, reverse=True)
65+
66+
return direct_to_template(request,
67+
"announcements/nomcomREDESIGN.html",
68+
{ 'curr_chair' : regimes[0]["chair"],
69+
'regimes' : regimes })
70+
71+
72+
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
73+
nomcom = nomcomREDESIGN
74+
75+
76+
def message_detail(request, object_id, queryset):
77+
from group.models import Group
78+
from ietf.announcements.models import Message
79+
80+
# restrict to nomcom announcements for the time being
81+
nomcoms = Group.objects.filter(acronym__startswith="nomcom").exclude(acronym="nomcom")
82+
m = get_object_or_404(Message, id=object_id,
83+
related_groups__in=nomcoms)
84+
85+
return direct_to_template(request,
86+
"announcements/message_detail.html",
87+
dict(message=m))
88+
89+

ietf/bin/expire-ids

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ if not in_id_expire_freeze():
1515
for doc in get_expired_ids():
1616
send_expire_notice_for_id(doc)
1717
expire_id(doc)
18-
syslog.syslog("Expired %s (id=%s)%s" % (doc.file_tag(), doc.id_document_tag, " in the ID Tracker" if doc.idinternal else ""))
18+
syslog.syslog("Expired %s (id=%s)%s" % (doc.file_tag(), doc.pk, " in the ID Tracker" if doc.latest_event(type="started_iesg_process") else ""))
1919

2020
clean_up_id_files()

ietf/bin/expire-last-calls

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ from ietf.idrfc.lastcall import *
1414
drafts = get_expired_last_calls()
1515
for doc in drafts:
1616
expire_last_call(doc)
17-
syslog.syslog("Expired last call for %s (id=%s)" % (doc.file_tag(), doc.id_document_tag))
17+
syslog.syslog("Expired last call for %s (id=%s)" % (doc.file_tag(), doc.pk))

0 commit comments

Comments
 (0)