Skip to content

Commit cbfe489

Browse files
committed
Merged in more shim-layer removals from olau@iola.dk
(-r5465:HEAD from branch/iola/shimfree). Copying relevant commit messages here: - Deleted dead code in many places. - Renamed id-something to draft-something, make the "is this eligible for expiration" logic clearer - Added a name for IPR search URL - Revamped the ballot popup view - URL reversed the IPR search link instead of hardcoding it - Cleaned up search views and remove dead code, port them to the new DB schema, hack related views in iesg/ and wginfo/ to use the new search interfaces, avoid camelCase in search GET parameters (with backwards-compat fallback), add some simple search unit tests, remove caching from views_search.py index pages as they're now pretty fast to generate, rewrite ballot popup JS, regularize some CSS classes to use hyphen-notation rather than camelCase, move some of the search templates to doc/. idrfc/ now mostly contains some wrapper code still in use by other subdirs, some ported code not yet moved, and dead code. - Fixed output bug in test crawler and print referrer upon errors so it's easier to figure out where a link came from - Added /doc/in-last-call/ to crawler, report original page as referrer in a redirect chain rather than intermediate URL - Ported idindex to new schema, speed them up, add tests, refactor index page in views_search to share code with the text index file, get rid of some special-case idindex filters from ietf_filters, move "/drafts/" redirects to a file in /doc/ - Ported /idtracker/status/ and /idtracker/status/last-call/ overview of drafts in IESG process to new schema in /doc/iesg/ and /doc/iesg/last-call/ - Added redirects for all of /idtracker/*, removed all view code and other dead code from idtracker/ - Removed the idtracker sitemap indexing drafts - in its current form, it adds nothing of value to the HTML-based /doc/all/ view, and it's pretty slow - Ported idtracker feeds to new schema, move them to doc/, cleaned up idtracker/ - only templatetags/ietf_filters and proxy code is left - Legacy-Id: 5836
2 parents bd76041 + 374a2da commit cbfe489

97 files changed

Lines changed: 1891 additions & 2223 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.

bin/mkrelease

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ Regards,
231231
Henrik
232232
(via the mkrelease script)
233233
" > ~/src/db/release-mail-v$VER.txt
234-
cat ~/src/db/release-mail-v$VER.txt | $do mail -s "New datatracker release: v$VER" -c henrik@levkowetz.com -c glen@amsl.com -c fenner@fenron.net -c rjs@nostrum.com -c housley@vigilsec.com -c cmorgan@amsl.com -c avezza@amsl.com -c amorris@amsl.com -c smccammon@amsl.com -c kmoreland@amsl.com -c stevey@amsl.com -c wchen@amsl.com -c olau@iola.dk $contributors codesprints@ietf.org
234+
cat ~/src/db/release-mail-v$VER.txt | $do mail -s "New datatracker release: v$VER" -c henrik@levkowetz.com -c glen@amsl.com -c fenner@fenron.net -c rjs@nostrum.com -c housley@vigilsec.com -c cmorgan@amsl.com -c avezza@amsl.com -c amorris@amsl.com -c smccammon@amsl.com -c kmoreland@amsl.com -c stevey@amsl.com -c olau@iola.dk $contributors codesprints@ietf.org
235235

236236
$do toolsfeed control changelog /www/tools.ietf.org/tools/atomfeed.xml
237237
$do toolpush /www/tools.ietf.org/tools/atomfeed.xml

ietf/bin/expire-ids

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@ syslog.openlog(os.path.basename(__file__), syslog.LOG_PID, syslog.LOG_USER)
1111

1212
from ietf.idrfc.expire import *
1313

14-
if not in_id_expire_freeze():
15-
for doc in get_expired_ids():
16-
send_expire_notice_for_id(doc)
17-
expire_id(doc)
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 ""))
14+
if not in_draft_expire_freeze():
15+
for doc in get_expired_drafts():
16+
send_expire_notice_for_draft(doc)
17+
expire_draft(doc)
18+
syslog.syslog("Expired draft %s-%s" % (doc.name, doc.rev))
1919

20-
clean_up_id_files()
20+
syslog.syslog("Cleaning up draft files")
21+
clean_up_draft_files()

ietf/bin/notify-expirations

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ from ietf import settings
66
from django.core import management
77
management.setup_environ(settings)
88

9-
from ietf.idrfc.expire import get_soon_to_expire_ids, send_expire_warning_for_id
9+
from ietf.idrfc.expire import get_soon_to_expire_drafts, send_expire_warning_for_draft
1010

1111

1212
# notify about documents that expire within the next 2 weeks
13-
notify_days = 14
13+
notify_days = 14
1414

15-
for doc in get_soon_to_expire_ids(notify_days):
16-
send_expire_warning_for_id(doc)
15+
for doc in get_soon_to_expire_drafts(notify_days):
16+
send_expire_warning_for_draft(doc)

ietf/bin/test-crawl

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ connection.queries = DontSaveQueries()
2424
MAX_URL_LENGTH = 500
2525
SLOW_THRESHOLD = 1.0
2626

27+
initial = ["/doc/all/", "/doc/in-last-call/"]
28+
29+
visited = set()
30+
urls = {} # url -> referrer
31+
32+
2733
def strip_url(url):
2834
if url.startswith("http://testserver"):
2935
url = url[len("http://testserver"):]
@@ -40,15 +46,13 @@ def extract_html_urls(content):
4046

4147
yield url
4248

43-
44-
visited = set()
45-
blacklist = set()
46-
urls = set(["/doc/all/"])
47-
4849
client = django.test.Client()
4950

51+
for url in initial:
52+
urls[url] = "[initial]"
53+
5054
while urls:
51-
url = urls.pop()
55+
url, referrer = urls.popitem()
5256

5357
visited.add(url)
5458

@@ -62,15 +66,15 @@ while urls:
6266
except:
6367
print "FAIL", url
6468
print "============="
65-
traceback.print_exc()
69+
print traceback.format_exc()
6670
print "============="
6771
else:
6872
tags = []
6973

7074
if r.status_code in (301, 302):
7175
u = strip_url(r["Location"])
7276
if u not in visited and u not in urls:
73-
urls.add(u)
77+
urls[u] = referrer # referrer is original referrer, not redirected url
7478

7579
elif r.status_code == 200:
7680
ctype = r["Content-Type"]
@@ -80,9 +84,9 @@ while urls:
8084
if ctype == "text/html":
8185
for u in extract_html_urls(r.content):
8286
if u not in visited and u not in urls:
83-
urls.add(u)
87+
urls[u] = url
8488
else:
85-
tags.append("FAIL")
89+
tags.append(u"FAIL (from %s)" % referrer)
8690

8791
if elapsed.total_seconds() > SLOW_THRESHOLD:
8892
tags.append("SLOW")

ietf/doc/feeds.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# Copyright The IETF Trust 2007, All Rights Reserved
2+
3+
import datetime, re
4+
5+
from django.conf import settings
6+
from django.contrib.syndication.feeds import Feed, FeedDoesNotExist
7+
from django.utils.feedgenerator import Atom1Feed
8+
from django.core.urlresolvers import reverse as urlreverse
9+
from django.template.defaultfilters import truncatewords_html, date as datefilter, linebreaks
10+
from django.utils.html import strip_tags
11+
from django.utils.text import truncate_words
12+
13+
from ietf.doc.models import *
14+
from ietf.doc.utils import augment_events_with_revision
15+
from ietf.idtracker.templatetags.ietf_filters import format_textarea
16+
17+
class DocumentChanges(Feed):
18+
feed_type = Atom1Feed
19+
20+
def get_object(self, bits):
21+
if len(bits) != 1:
22+
raise Document.DoesNotExist
23+
24+
return Document.objects.get(docalias__name=bits[0])
25+
26+
def title(self, obj):
27+
return "Changes for %s" % obj.display_name()
28+
29+
def link(self, obj):
30+
if obj is None:
31+
raise FeedDoesNotExist
32+
if not hasattr(self, "cached_link"):
33+
self.cached_link = urlreverse("doc_history", kwargs=dict(name=obj.canonical_name()))
34+
return self.cached_link
35+
36+
def subtitle(self, obj):
37+
return "History of change entries for %s." % obj.display_name()
38+
39+
def items(self, obj):
40+
events = obj.docevent_set.all().order_by("-time","-id")
41+
augment_events_with_revision(obj, events)
42+
return events
43+
44+
def item_title(self, item):
45+
return u"[%s] %s [rev. %s]" % (item.by, truncate_words(strip_tags(item.desc), 15), item.rev)
46+
47+
def item_description(self, item):
48+
return truncatewords_html(format_textarea(item.desc), 20)
49+
50+
def item_pubdate(self, item):
51+
return item.time
52+
53+
def item_author_name(self, item):
54+
return unicode(item.by)
55+
56+
def item_link(self, item):
57+
return self.cached_link + "#history-%s" % item.pk
58+
59+
class InLastCall(Feed):
60+
title = "Documents in Last Call"
61+
subtitle = "Announcements for documents in last call."
62+
feed_type = Atom1Feed
63+
author_name = 'IESG Secretary'
64+
link = "/doc/iesg/last-call/"
65+
66+
def items(self):
67+
docs = list(Document.objects.filter(type="draft", states=State.objects.get(type="draft-iesg", slug="lc")))
68+
for d in docs:
69+
d.lc_event = d.latest_event(LastCallDocEvent, type="sent_last_call")
70+
71+
docs = [d for d in docs if d.lc_event]
72+
docs.sort(key=lambda d: d.lc_event.expires)
73+
74+
return docs
75+
76+
def item_title(self, item):
77+
return u"%s (%s - %s)" % (item.name,
78+
datefilter(item.lc_event.time, "F j"),
79+
datefilter(item.lc_event.expires, "F j, Y"))
80+
81+
def item_description(self, item):
82+
return linebreaks(item.lc_event.desc)
83+
84+
def item_pubdate(self, item):
85+
return item.lc_event.time
86+

ietf/doc/models.py

Lines changed: 35 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ def __unicode__(self):
3737
class Meta:
3838
ordering = ["type", "order"]
3939

40+
IESG_BALLOT_ACTIVE_STATES = ("lc", "writeupw", "goaheadw", "iesg-eva", "defer")
41+
IESG_SUBSTATE_TAGS = ('point', 'ad-f-up', 'need-rev', 'extpty')
42+
4043
class DocumentInfo(models.Model):
4144
"""Any kind of document. Draft, RFC, Charter, IPR Statement, Liaison Statement"""
4245
time = models.DateTimeField(default=datetime.datetime.now) # should probably have auto_now=True
@@ -186,9 +189,7 @@ def __unicode__(self):
186189
def get_absolute_url(self):
187190
name = self.name
188191
if self.type_id == "draft" and self.get_state_slug() == "rfc":
189-
aliases = self.docalias_set.filter(name__startswith="rfc")
190-
if aliases:
191-
name = aliases[0].name
192+
name = self.canonical_name()
192193
elif self.type_id in ('slides','agenda','minutes'):
193194
session = self.session_set.all()[0]
194195
meeting = session.meeting
@@ -260,11 +261,10 @@ def related_that_doc(self, relationship):
260261
raise TypeError("Expected a string, tuple or list, received %s" % type(relationship))
261262
return DocAlias.objects.filter(relateddocument__source=self, relateddocument__relationship__in=relationship)
262263

263-
#TODO can/should this be a function instead of a property? Currently a view uses it as a property
264-
@property
265-
def telechat_date(self):
266-
e = self.latest_event(TelechatDocEvent, type="scheduled_for_telechat")
267-
return e.telechat_date if e else None
264+
def telechat_date(self, e=None):
265+
if not e:
266+
e = self.latest_event(TelechatDocEvent, type="scheduled_for_telechat")
267+
return e.telechat_date if e and e.telechat_date and e.telechat_date >= datetime.date.today() else None
268268

269269
def area_acronym(self):
270270
g = self.group
@@ -283,10 +283,6 @@ def group_acronym(self):
283283
else:
284284
return "none"
285285

286-
def on_upcoming_agenda(self):
287-
e = self.latest_event(TelechatDocEvent, type="scheduled_for_telechat")
288-
return bool(e and e.telechat_date and e.telechat_date >= datetime.date.today())
289-
290286
def returning_item(self):
291287
e = self.latest_event(TelechatDocEvent, type="scheduled_for_telechat")
292288
return e.returning_item if e else None
@@ -311,56 +307,56 @@ def displayname_with_link(self):
311307
return '<a href="%s">%s-%s</a>' % (self.get_absolute_url(), self.name , self.rev)
312308

313309
def rfc_number(self):
314-
qs = self.docalias_set.filter(name__startswith='rfc')
315-
return qs[0].name[3:] if qs else None
310+
n = self.canonical_name()
311+
return n[3:] if n.startswith("rfc") else None
316312

317313
def friendly_state(self):
318-
""" Return a concise text description of the document's current state """
319-
if self.type_id=='draft':
320-
# started_iesg_process is is how the redesigned database schema (as of May2012) captured what
321-
# used to be "has an IDInternal", aka *Wrapper.in_ietf_process()=True
322-
in_iesg_process = self.latest_event(type='started_iesg_process')
323-
iesg_state_summary=None
324-
if in_iesg_process:
325-
iesg_state = self.states.get(type='draft-iesg')
314+
""" Return a concise text description of the document's current state."""
315+
state = self.get_state()
316+
if not state:
317+
return "Unknown state"
318+
319+
if self.type_id == 'draft':
320+
iesg_state = self.get_state("draft-iesg")
321+
iesg_state_summary = None
322+
if iesg_state:
326323
# This knowledge about which tags are reportable IESG substate tags is duplicated in idrfc
327-
IESG_SUBSTATE_TAGS = ('point', 'ad-f-up', 'need-rev', 'extpty')
328324
iesg_substate = self.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
329325
# There really shouldn't be more than one tag in iesg_substate, but this will do something sort-of-sensible if there is
330326
iesg_state_summary = iesg_state.name
331327
if iesg_substate:
332328
iesg_state_summary = iesg_state_summary + "::"+"::".join(tag.name for tag in iesg_substate)
333329

334-
if self.get_state_slug() == "rfc":
335-
n = self.rfc_number()
336-
return "<a href=\"%s\">RFC %s</a>" % (urlreverse('doc_view', kwargs=dict(name='rfc%s' % n)), n)
337-
elif self.get_state_slug() == "repl":
330+
if state.slug == "rfc":
331+
return "RFC %s (%s)" % (self.rfc_number(), self.std_level)
332+
elif state.slug == "repl":
338333
rs = self.related_that("replaces")
339334
if rs:
340-
return mark_safe("Replaced by " + ", ".join("<a href=\"%s\">%s</a>" % (urlreverse('doc_view', args=[name]), name) for name in rs))
335+
return mark_safe("Replaced by " + ", ".join("<a href=\"%s\">%s</a>" % (urlreverse('doc_view', kwargs=dict(name=name)), name) for name in rs))
341336
else:
342337
return "Replaced"
343-
elif self.get_state_slug() == "active":
344-
if in_iesg_process:
338+
elif state.slug == "active":
339+
if iesg_state:
345340
if iesg_state.slug == "dead":
346341
# Many drafts in the draft-iesg "Dead" state are not dead
347342
# in other state machines; they're just not currently under
348343
# IESG processing. Show them as "I-D Exists (IESG: Dead)" instead...
349-
return "I-D Exists (IESG: "+iesg_state_summary+")"
344+
return "I-D Exists (IESG: %s)" % iesg_state_summary
350345
elif iesg_state.slug == "lc":
351-
expiration_date = str(self.latest_event(LastCallDocEvent,type="sent_last_call").expires.date())
352-
return iesg_state_summary + " (ends "+expiration_date+")"
353-
else:
354-
return iesg_state_summary
346+
e = self.latest_event(LastCallDocEvent, type="sent_last_call")
347+
if e:
348+
return iesg_state_summary + " (ends %s)" % e.expires.date().isoformat()
349+
350+
return iesg_state_summary
355351
else:
356352
return "I-D Exists"
357353
else:
358-
if in_iesg_process and iesg_state.slug == "dead":
359-
return self.get_state().name +" (IESG: "+iesg_state_summary+")"
354+
if iesg_state and iesg_state.slug == "dead":
355+
return state.name + " (IESG: %s)" % iesg_state_summary
360356
# Expired/Withdrawn by Submitter/IETF
361-
return self.get_state().name
357+
return state.name
362358
else:
363-
return self.get_state().name
359+
return state.name
364360

365361
def ipr(self):
366362
"""Returns the IPR disclosures against this document (as a queryset over IprDocAlias)."""

ietf/doc/redirect_drafts_urls.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Copyright The IETF Trust 2007, All Rights Reserved
2+
3+
from django.conf import settings
4+
from django.conf.urls.defaults import patterns
5+
6+
7+
from django.http import HttpResponsePermanentRedirect
8+
from django.shortcuts import get_object_or_404
9+
10+
from ietf.group.models import Group
11+
12+
urlpatterns = patterns('',
13+
(r'^$', 'django.views.generic.simple.redirect_to', { 'url': '/doc/'}),
14+
(r'^all/$', 'django.views.generic.simple.redirect_to', { 'url': '/doc/all/'}),
15+
(r'^rfc/$', 'django.views.generic.simple.redirect_to', { 'url': '/doc/all/#rfc'}),
16+
(r'^dead/$', 'django.views.generic.simple.redirect_to', { 'url': '/doc/all/#expired'}),
17+
(r'^current/$', 'django.views.generic.simple.redirect_to', { 'url': '/doc/active/'}),
18+
(r'^(?P<object_id>\d+)/(related/)?$', 'django.views.generic.simple.redirect_to', { 'url': '/doc/' }),
19+
(r'^(?P<name>[^/]+)/(related/)?$', 'django.views.generic.simple.redirect_to', { 'url': '/doc/%(name)s/' }),
20+
(r'^wgid/(?P<id>\d+)/$', lambda request, id: HttpResponsePermanentRedirect("/wg/%s/" % get_object_or_404(Group, id=id).acronym)),
21+
(r'^wg/(?P<acronym>[^/]+)/$', 'django.views.generic.simple.redirect_to', { 'url': '/wg/%(acronym)s/' }),
22+
(r'^all_id(?:_txt)?.html$', 'django.views.generic.simple.redirect_to', { 'url': 'http://www.ietf.org/id/all_id.txt' }),
23+
)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from django.conf.urls.defaults import patterns, url
2+
from django.views.generic.simple import redirect_to
3+
4+
urlpatterns = patterns('',
5+
(r'^help/(?:sub)?state/(?:\d+/)?$', redirect_to, {'url': '/doc/help/state/draft-iesg/' }),
6+
(r'^help/evaluation/$', redirect_to, {'url':'http://www.ietf.org/iesg/voting-procedures.html' }),
7+
(r'^status/$', redirect_to, {'url':'/doc/iesg/' }),
8+
(r'^status/last-call/$', redirect_to, {'url':'/doc/iesg/last-call/' }),
9+
(r'^rfc0*(?P<rfc_number>\d+)/$', redirect_to, {'url':'/doc/rfc%(rfc_number)s/' }),
10+
(r'^(?P<name>[^/]+)/$', redirect_to, {'url':'/doc/%(name)s/' }),
11+
(r'^(?P<name>[^/]+)/comment/\d+/$', redirect_to, {'url':'/doc/%(name)s/history/' }),
12+
(r'^$', redirect_to, { 'url': '/doc/'}),
13+
)

0 commit comments

Comments
 (0)