Skip to content

Commit 2dee1bd

Browse files
committed
Import more history and fix import/proxy bugs (enough to get draft-arkko-townsley-coexistence working), more proxying for group/person related things (enough to get left base menu working)
- Legacy-Id: 2714
1 parent d49f761 commit 2dee1bd

12 files changed

Lines changed: 399 additions & 89 deletions

File tree

ietf/idrfc/idrfc_wrapper.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,7 @@ def _init(self):
622622
p = dict(ad_name=pos.ad.get_name(),
623623
ad_username="", # FIXME: don't seem to have username at the moment
624624
position=pos.pos.name,
625-
is_old_ad=pos.ad in active_ads,
625+
is_old_ad=pos.ad not in active_ads,
626626
old_positions=[])
627627

628628
if pos.pos.slug == "discuss":

ietf/idrfc/views_doc.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,14 +148,30 @@ def document_main(request, name):
148148
def _get_history(doc, versions):
149149
results = []
150150
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
151+
versions = [] # clear versions
151152
for e in doc._draft.event_set.all().select_related('by').order_by('-time'):
152153
info = {}
154+
if e.type == "new_revision":
155+
filename = u"%s-%s" % (e.doc.name, e.newrevision.rev)
156+
e.desc = 'New version available: <a href="http://tools.ietf.org/id/%s.txt">%s</a>' % (filename, filename)
157+
if int(e.newrevision.rev) != 0:
158+
e.desc += ' (<a href="http://tools.ietf.org/rfcdiff?url2=%s">diff from -%02d</a>)' % (filename, int(e.newrevision.rev) - 1)
159+
info["dontmolest"] = True
160+
153161
info['text'] = e.desc
154162
info['by'] = e.by.get_name()
155163
info['textSnippet'] = truncatewords_html(format_textarea(fill(info['text'], 80)), 25)
156-
info['snipped'] = info['textSnippet'][-3:] == "..."
157-
e.version = e.doc.rev
164+
info['snipped'] = info['textSnippet'][-3:] == "..." and e.type != "new_revision"
158165
results.append({'comment':e, 'info':info, 'date':e.time, 'is_com':True})
166+
167+
prev_rev = "00"
168+
for o in reversed(results):
169+
e = o["comment"]
170+
if e.type == "new_revision":
171+
e.version = e.newrevision.rev
172+
else:
173+
e.version = prev_rev
174+
prev_rev = e.version
159175
else:
160176
if doc.is_id_wrapper:
161177
comments = DocumentComment.objects.filter(document=doc.tracker_id).exclude(rfc_flag=1)

ietf/idrfc/views_edit.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ def diff(obj, attr, name):
236236
setattr(obj, attr, r[attr])
237237

238238
diff(doc, 'intended_status', "Intended Status")
239-
diff(doc.idinternal, 'status_date', "Status Date")
239+
diff(doc.idinternal, 'status_date', "Status date")
240240
if 'area_acronym' in r and r['area_acronym']:
241241
diff(doc.idinternal, 'area_acronym', 'Area acronym')
242242
diff(doc.idinternal, 'job_owner', 'Responsible AD')

ietf/templates/idrfc/doc_history.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,12 @@
6565
{{ c.info.text|fill:"80"|safe|urlize|linebreaksbr|keep_spacing|sanitize_html|safe }}
6666
</div>
6767
{% else %}
68+
{% if c.info.dontmolest %}
69+
{{ c.info.text|safe }}
70+
{% else %}
6871
{{ c.info.text|fill:"80"|safe|urlize|linebreaksbr|keep_spacing|sanitize_html|safe }}
6972
{% endif %}
73+
{% endif %}
7074
</td>
7175
{% endif %}
7276

redesign/doc/admin.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class EventAdmin(admin.ModelAdmin):
4040
admin.site.register(Message, EventAdmin)
4141
admin.site.register(Text, EventAdmin)
4242
admin.site.register(BallotPosition, EventAdmin)
43+
admin.site.register(Status, EventAdmin)
4344
admin.site.register(Expiration, EventAdmin)
4445
admin.site.register(Telechat, EventAdmin)
4546

redesign/doc/models.py

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from redesign.person.models import Email
77
from redesign.util import admin_link
88

9+
import datetime
910

1011
class RelatedDoc(models.Model):
1112
relationship = models.ForeignKey(DocRelationshipName)
@@ -49,12 +50,13 @@ class Meta:
4950
abstract = True
5051
def author_list(self):
5152
return ", ".join(email.address for email in self.authors.all())
52-
def latest_event(self, **filter_args):
53-
e = self.event_set.filter(**filter_args).order_by('-time')[:1]
54-
if e:
55-
return e[0]
56-
else:
57-
return None
53+
def latest_event(self, *args, **filter_args):
54+
"""Get latest event with specific requirements, e.g.
55+
d.latest_event(type="xyz") returns an Event while
56+
d.latest_event(Status, type="xyz") returns a Status event."""
57+
model = args[0] if args else Event
58+
e = model.objects.filter(doc=self).filter(**filter_args).order_by('-time')[:1]
59+
return e[0] if e else None
5860

5961
class Document(DocumentInfo):
6062
name = models.CharField(max_length=255, primary_key=True) # immutable
@@ -150,6 +152,7 @@ class SendQueue(models.Model):
150152
("changed_document", "Changed document metadata"),
151153

152154
# misc document events
155+
("added_comment", "Added comment"),
153156
("added_tombstone", "Added tombstone"),
154157
("requested_resurrect", "Requested resurrect"),
155158

@@ -163,6 +166,9 @@ class SendQueue(models.Model):
163166

164167
("changed_last_call_text", "Changed last call text"),
165168
("sent_last_call", "Sent last call"),
169+
("requested_last_call", "Requested last call"),
170+
171+
("changed_status_date", "Changed status date"),
166172

167173
("scheduled_for_telechat", "Scheduled for telechat"),
168174

@@ -174,9 +180,9 @@ class SendQueue(models.Model):
174180

175181
class Event(models.Model):
176182
"""An occurrence in connection with a document."""
177-
time = models.DateTimeField()
183+
time = models.DateTimeField(default=datetime.datetime.now, help_text="When the event happened")
178184
type = models.CharField(max_length=50, choices=EVENT_TYPES)
179-
by = models.ForeignKey(Email, blank=True, null=True)
185+
by = models.ForeignKey(Email, blank=True, null=True) # FIXME: make NOT NULL?
180186
doc = models.ForeignKey('doc.Document')
181187
desc = models.TextField()
182188

@@ -192,7 +198,10 @@ class Message(Event):
192198

193199
class Text(Event):
194200
content = models.TextField(blank=True)
195-
201+
202+
class NewRevision(Event):
203+
rev = models.CharField(max_length=16)
204+
196205
# IESG events
197206
class BallotPosition(Event):
198207
ad = models.ForeignKey(Email)
@@ -202,6 +211,9 @@ class BallotPosition(Event):
202211
comment = models.TextField(help_text="Optional comment", blank=True)
203212
comment_time = models.DateTimeField(help_text="Time optional comment was written", blank=True, null=True)
204213

214+
class Status(Event):
215+
date = models.DateField()
216+
205217
class Expiration(Event):
206218
expires = models.DateTimeField()
207219

redesign/doc/proxy.py

Lines changed: 54 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
from redesign.person.models import Email
33
from redesign.proxy_utils import TranslatingManager
44

5+
from django.conf import settings
6+
7+
import glob, os
8+
59

610
class InternetDraft(Document):
711
objects = TranslatingManager(dict(filename="name",
@@ -12,53 +16,61 @@ class InternetDraft(Document):
1216

1317
# things from InternetDraft
1418

15-
# id_document_tag = models.AutoField(primary_key=True)
19+
#id_document_tag = models.AutoField(primary_key=True)
1620
@property
1721
def id_document_tag(self):
1822
return self.name # Will only work for some use cases
19-
# title = models.CharField(max_length=255, db_column='id_document_name') # same name
20-
# id_document_key = models.CharField(max_length=255, editable=False)
23+
#title = models.CharField(max_length=255, db_column='id_document_name') # same name
24+
#id_document_key = models.CharField(max_length=255, editable=False)
2125
@property
2226
def id_document_key(self):
2327
return self.title.upper()
24-
# group = models.ForeignKey(Acronym, db_column='group_acronym_id')
28+
#group = models.ForeignKey(Acronym, db_column='group_acronym_id')
2529
@property
2630
def group(self):
27-
return super(self.__class__, self).group
28-
# filename = models.CharField(max_length=255, unique=True)
31+
from group.proxy import Acronym as AcronymProxy
32+
return AcronymProxy(super(self.__class__, self).group)
33+
#filename = models.CharField(max_length=255, unique=True)
2934
@property
3035
def filename(self):
3136
return self.name
32-
# revision = models.CharField(max_length=2)
37+
#revision = models.CharField(max_length=2)
3338
@property
3439
def revision(self):
3540
return self.rev
36-
# revision_date = models.DateField()
41+
#revision_date = models.DateField()
3742
@property
3843
def revision_date(self):
3944
e = self.latest_event(type="new_revision")
40-
return e.time if e else None
41-
# file_type = models.CharField(max_length=20)
45+
return e.time.date() if e else None
46+
#file_type = models.CharField(max_length=20)
4247
@property
4348
def file_type(self):
44-
return ".txt" # FIXME XXX should look in the repository to see what's available
45-
# txt_page_count = models.IntegerField()
49+
matches = glob.glob(os.path.join(settings.INTERNET_DRAFT_PATH, self.filename + "*.*"))
50+
possible_types = [".txt", ".pdf", ".xml", ".ps"]
51+
res = set()
52+
for m in matches:
53+
for t in possible_types:
54+
if m.endswith(t):
55+
res.add(t)
56+
return ",".join(res)
57+
#txt_page_count = models.IntegerField()
4658
@property
4759
def txt_page_count(self):
4860
return self.pages
49-
# local_path = models.CharField(max_length=255, blank=True) # unused
50-
# start_date = models.DateField()
61+
#local_path = models.CharField(max_length=255, blank=True) # unused
62+
#start_date = models.DateField()
5163
@property
5264
def start_date(self):
5365
return self.dochistory_set.dates("time","day","ASC")[0]
54-
# expiration_date = models.DateField()
66+
#expiration_date = models.DateField()
5567
@property
5668
def expiration_date(self):
5769
return self.expiration()
58-
# abstract = models.TextField() # same name
59-
# dunn_sent_date = models.DateField(null=True, blank=True) # unused
60-
# extension_date = models.DateField(null=True, blank=True) # unused
61-
# status = models.ForeignKey(IDStatus)
70+
#abstract = models.TextField() # same name
71+
#dunn_sent_date = models.DateField(null=True, blank=True) # unused
72+
#extension_date = models.DateField(null=True, blank=True) # unused
73+
#status = models.ForeignKey(IDStatus)
6274
@property
6375
def status(self):
6476
from redesign.name.proxy import IDStatus
@@ -69,63 +81,63 @@ def status_id(self):
6981
from redesign.name.proxy import IDStatus
7082
return { 'active': 1, 'repl': 5, 'expired': 2, 'rfc': 3, 'auth-rm': 4, 'ietf-rm': 6 }[self.state_id]
7183

72-
# intended_status = models.ForeignKey(IDIntendedStatus)
84+
#intended_status = models.ForeignKey(IDIntendedStatus)
7385
@property
7486
def intended_status(self):
7587
return self.intended_std_level
7688

77-
# lc_sent_date = models.DateField(null=True, blank=True)
89+
#lc_sent_date = models.DateField(null=True, blank=True)
7890
@property
7991
def lc_sent_date(self):
8092
e = self.latest_event(type="sent_last_call")
8193
return e.time if e else None
8294

83-
# lc_changes = models.CharField(max_length=3) # used in DB, unused in Django code?
95+
#lc_changes = models.CharField(max_length=3) # used in DB, unused in Django code?
8496

85-
# lc_expiration_date = models.DateField(null=True, blank=True)
97+
#lc_expiration_date = models.DateField(null=True, blank=True)
8698
@property
8799
def lc_expiration_date(self):
88100
e = self.latest_event(type="sent_last_call")
89101
return e.expiration.expires if e else None
90102

91-
# b_sent_date = models.DateField(null=True, blank=True)
103+
#b_sent_date = models.DateField(null=True, blank=True)
92104
@property
93105
def b_sent_date(self):
94106
e = self.latest_event(type="sent_ballot_announcement")
95107
return e.time if e else None
96108

97-
# b_discussion_date = models.DateField(null=True, blank=True) # unused
109+
#b_discussion_date = models.DateField(null=True, blank=True) # unused
98110

99-
# b_approve_date = models.DateField(null=True, blank=True)
111+
#b_approve_date = models.DateField(null=True, blank=True)
100112
@property
101113
def b_approve_date(self):
102114
e = self.latest_event(type="approved_ballot")
103115
return e.time if e else None
104116

105-
# wgreturn_date = models.DateField(null=True, blank=True) # unused
117+
#wgreturn_date = models.DateField(null=True, blank=True) # unused
106118

107-
# rfc_number = models.IntegerField(null=True, blank=True, db_index=True)
119+
#rfc_number = models.IntegerField(null=True, blank=True, db_index=True)
108120
@property
109121
def rfc_number(self):
110122
try:
111123
self.docalias_set.filter(name__startswith="rfc")[0].name[3:]
112124
except IndexError:
113125
return None
114126

115-
# comments = models.TextField(blank=True) # unused
127+
#comments = models.TextField(blank=True) # unused
116128

117-
# last_modified_date = models.DateField()
129+
#last_modified_date = models.DateField()
118130
@property
119131
def last_modified_date(self):
120132
return self.time
121133

122-
# replaced_by = models.ForeignKey('self', db_column='replaced_by', blank=True, null=True, related_name='replaces_set')
134+
#replaced_by = models.ForeignKey('self', db_column='replaced_by', blank=True, null=True, related_name='replaces_set')
123135
@property
124136
def replaced_by(self):
125137
r = InternetDraft.objects.filter(docalias__relateddoc__relationship="replaces", docalias__relateddoc__related_document_set=self)
126138
return r[0] if r else None
127139

128-
# replaces = FKAsOneToOne('replaces', reverse=True)
140+
#replaces = FKAsOneToOne('replaces', reverse=True)
129141
@property
130142
def replaces(self):
131143
r = InternetDraft.objects.filter(related__doc_alias__document=self, related__relationship="replaces")
@@ -137,17 +149,17 @@ def replaces_set(self):
137149
# this is replaced_by
138150
return InternetDraft.objects.filter(docalias__relateddoc__relationship="replaces", docalias__relateddoc__related_document_set=self)
139151

140-
# review_by_rfc_editor = models.BooleanField()
152+
#review_by_rfc_editor = models.BooleanField()
141153
@property
142154
def review_by_rfc_editor(self): raise NotImplemented # should use tag
143155

144-
# expired_tombstone = models.BooleanField()
156+
#expired_tombstone = models.BooleanField()
145157
@property
146158
def expired_tombstone(self):
147159
# FIXME: this is probably not perfect, what happens when we delete it again
148160
return self.latest_event(type="added_tombstone")
149161

150-
# idinternal = FKAsOneToOne('idinternal', reverse=True, query=models.Q(rfc_flag = 0))
162+
#idinternal = FKAsOneToOne('idinternal', reverse=True, query=models.Q(rfc_flag = 0))
151163
@property
152164
def idinternal(self):
153165
return self if self.iesg_state else None
@@ -246,7 +258,9 @@ def token_email(self):
246258

247259
#status_date = models.DateField(blank=True,null=True)
248260
@property
249-
def status_date(self): raise NotImplemented # FIXME
261+
def status_date(self):
262+
e = self.latest_event(Status, type="changed_status_date")
263+
return e.date if e else None
250264

251265
#email_display = models.CharField(blank=True, max_length=50) # unused
252266
#agenda = models.IntegerField(null=True, blank=True)
@@ -276,7 +290,8 @@ def mark_by(self):
276290
# job_owner = models.ForeignKey(IESGLogin, db_column='job_owner', related_name='documents')
277291
@property
278292
def job_owner(self):
279-
return self.ad
293+
from person.proxy import IESGLogin as IESGLoginProxy
294+
return IESGLoginProxy(self.ad)
280295

281296
#event_date = models.DateField(null=True)
282297
@property
@@ -485,7 +500,7 @@ def needed(self, standardsTrack=True):
485500

486501
yes = noobj = discuss = recuse = 0
487502
for position in positions:
488-
p = position.pos_id
503+
p = position.ballotposition.pos_id
489504
if p == "yes":
490505
yes += 1
491506
if p == "noobj":
@@ -505,7 +520,7 @@ def needed(self, standardsTrack=True):
505520
if standardsTrack:
506521
# For standards-track, need positions from 2/3 of the
507522
# non-recused current IESG.
508-
needed = (len(ads) - recuse) * 2 / 3
523+
needed = int((len(ads) - recuse) * 2 / 3)
509524
else:
510525
# Info and experimental only need one position.
511526
needed = 1

0 commit comments

Comments
 (0)