Port idtracker feeds to new schema, move them to doc/, clean up

idtracker/ - only templatetags/ietf_filters and proxy code is left
 - Legacy-Id: 5643
This commit is contained in:
Ole Laursen 2013-04-11 14:20:42 +00:00
parent 564a97d2ee
commit 7892e29036
12 changed files with 95 additions and 215 deletions

86
ietf/doc/feeds.py Normal file
View file

@ -0,0 +1,86 @@
# Copyright The IETF Trust 2007, All Rights Reserved
import datetime, re
from django.conf import settings
from django.contrib.syndication.feeds import Feed, FeedDoesNotExist
from django.utils.feedgenerator import Atom1Feed
from django.core.urlresolvers import reverse as urlreverse
from django.template.defaultfilters import truncatewords_html, date as datefilter, linebreaks
from django.utils.html import strip_tags
from django.utils.text import truncate_words
from ietf.doc.models import *
from ietf.doc.utils import augment_events_with_revision
from ietf.idtracker.templatetags.ietf_filters import format_textarea
class DocumentChanges(Feed):
feed_type = Atom1Feed
def get_object(self, bits):
if len(bits) != 1:
raise Document.DoesNotExist
return Document.objects.get(docalias__name=bits[0])
def title(self, obj):
return "Changes for %s" % obj.display_name()
def link(self, obj):
if obj is None:
raise FeedDoesNotExist
if not hasattr(self, "cached_link"):
self.cached_link = urlreverse("doc_history", kwargs=dict(name=obj.canonical_name()))
return self.cached_link
def subtitle(self, obj):
return "History of change entries for %s." % obj.display_name()
def items(self, obj):
events = obj.docevent_set.all().order_by("-time","-id")
augment_events_with_revision(obj, events)
return events
def item_title(self, item):
return u"[%s] %s [rev. %s]" % (item.by, truncate_words(strip_tags(item.desc), 15), item.rev)
def item_description(self, item):
return truncatewords_html(format_textarea(item.desc), 20)
def item_pubdate(self, item):
return item.time
def item_author_name(self, item):
return unicode(item.by)
def item_link(self, item):
return self.cached_link + "#history-%s" % item.pk
class InLastCall(Feed):
title = "Documents in Last Call"
subtitle = "Announcements for documents in last call."
feed_type = Atom1Feed
author_name = 'IESG Secretary'
link = "/doc/iesg/last-call/"
def items(self):
docs = list(Document.objects.filter(type="draft", states=State.objects.get(type="draft-iesg", slug="lc")))
for d in docs:
d.lc_event = d.latest_event(LastCallDocEvent, type="sent_last_call")
docs = [d for d in docs if d.lc_event]
docs.sort(key=lambda d: d.lc_event.expires)
return docs
def item_title(self, item):
return u"%s (%s - %s)" % (item.name,
datefilter(item.lc_event.time, "F j"),
datefilter(item.lc_event.expires, "F j, Y"))
def item_description(self, item):
return linebreaks(item.lc_event.desc)
def item_pubdate(self, item):
return item.lc_event.time

View file

@ -403,8 +403,6 @@ def drafts_in_iesg_process(request, last_call_only=None):
grouped_docs.append((s, docs))
#drafts.sort(key=lambda d: (d.cur_state_id, d.status_date or datetime.date.min, d.b_sent_date or datetime.date.min))
return render_to_response('doc/drafts_in_iesg_process.html', {
"grouped_docs": grouped_docs,
"title": title,

View file

@ -1,72 +0,0 @@
# Copyright The IETF Trust 2007, All Rights Reserved
from django.conf import settings
from django.contrib.syndication.feeds import Feed, FeedDoesNotExist
from django.utils.feedgenerator import Atom1Feed
from ietf.idtracker.models import IDInternal
import datetime
import re
class DocumentComments(Feed):
feed_type = Atom1Feed
def get_object(self, bits):
if len(bits) != 1:
raise IDInternal.DoesNotExist
rfc = re.match('rfc(\d+)', bits[0])
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
return IDInternal.objects.get(docalias__name=bits[0])
if rfc:
return IDInternal.objects.get(draft=int(rfc.group(1)), rfc_flag=1)
else:
return IDInternal.objects.get(draft__filename=bits[0], rfc_flag=0)
def title(self, obj):
# filename is a function for RFCs and an attribute for I-Ds.
# This works transparently for templates but is not transparent
# for python.
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
return "I-D Tracker comments for %s" % obj.filename
if obj.rfc_flag:
filename = obj.document().filename()
else:
filename = obj.document().filename
return "I-D Tracker comments for %s" % filename
def link(self, obj):
if obj is None:
raise FeedDoesNotExist
return obj.get_absolute_url()
def description(self, obj):
return self.title(obj)
def items(self, obj):
return obj.public_comments().order_by("-date","-id")
def item_pubdate(self, item):
return item.datetime()
def item_author_name(self, item):
return item.get_author()
class InLastCall(Feed):
title = "Documents in Last Call"
feed_type = Atom1Feed
author_name = 'IESG Secretary'
link = "/idtracker/status/last-call/"
def items(self):
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
ret = list(IDInternal.objects.filter(states__type="draft-iesg", states__slug="lc"))
else:
ret = list(IDInternal.objects.filter(primary_flag=1).filter(cur_state__state='In Last Call'))
ret.sort(key=lambda item: (item.document().lc_expiration_date or datetime.date.today()))
return ret
def item_pubdate(self, item):
# this method needs to return a datetime instance, even
# though the database has only date, not time
return datetime.datetime.combine((item.document().lc_sent_date or datetime.datetime.now().date()), datetime.time(0,0,0))

View file

@ -1,42 +1,10 @@
# Copyright The IETF Trust 2007, All Rights Reserved
#
import doctest
import doctest, unittest
from ietf.idtracker.templatetags import ietf_filters
import unittest
from ietf.utils.test_utils import SimpleUrlTestCase, canonicalize_feed, canonicalize_sitemap
import django.test
class TemplateTagTest(unittest.TestCase):
def testTemplateTags(self):
print " Testing ietf_filters"
#doctest.testmod(ietf_filters,verbose=True)
(failures, tests) = doctest.testmod(ietf_filters)
def test_template_tags(self):
failures, tests = doctest.testmod(ietf_filters)
self.assertEqual(failures, 0)
print "OK (ietf_filters)"
class IdTrackerUrlTestCase(SimpleUrlTestCase):
def testUrls(self):
self.doTestUrls(__file__)
def doCanonicalize(self, url, content):
if url.startswith("/feed/"):
return canonicalize_feed(content)
elif url.startswith("/sitemap"):
return canonicalize_sitemap(content)
else:
return content
# class WGRoleTest(django.test.TestCase):
# fixtures = ['wgtest']
#
# def setUp(self):
# from ietf.idtracker.models import IETFWG
# self.xmas = IETFWG.objects.get(group_acronym__acronym='xmas')
# self.snow = IETFWG.objects.get(group_acronym__acronym='snow')
#
# def test_roles(self):
# print " Testing WG roles"
# self.assertEquals(self.xmas.wgchair_set.all()[0].role(), 'xmas WG Chair')
# self.assertEquals(self.snow.wgchair_set.all()[0].role(), 'snow BOF Chair')
# self.assertEquals(self.xmas.wgsecretary_set.all()[0].role(), 'xmas WG Secretary')
# self.assertEquals(self.xmas.wgtechadvisor_set.all()[0].role(), 'xmas Technical Advisor')
# print "OK"

View file

@ -1,88 +0,0 @@
# Copyright The IETF Trust 2007, All Rights Reserved
# Create your views here.
from django.http import HttpResponsePermanentRedirect, Http404
from django.conf import settings
from django.template import RequestContext
from django.shortcuts import get_object_or_404, render_to_response
from django.views.generic.list_detail import object_detail, object_list
from ietf.idtracker.models import InternetDraft, IDInternal, IDState, IDSubState, BallotInfo, DocumentComment
import re, datetime
def state_desc(request, state, is_substate=0):
if int(state) == 100:
object = {
'state': 'I-D Exists',
'description': """
Initial (default) state for all internet drafts. Such documents are
not being tracked by the IESG as no request has been made of the
IESG to do anything with the document.
"""
}
elif is_substate:
sub = get_object_or_404(IDSubState, pk=state)
object = { 'state': sub.sub_state, 'description': sub.description }
else:
object = get_object_or_404(IDState, pk=state)
return render_to_response('idtracker/state_desc.html', {'state': object},
context_instance=RequestContext(request))
def status(request):
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
drafts = list(IDInternal.objects.filter(states__type="draft-iesg").exclude(states__type="draft-iesg", states__slug__in=('pub', 'dead', 'watching', 'rfcqueue')).distinct().order_by('states__order'))
drafts.sort(key=lambda d: (d.cur_state_id, d.status_date or datetime.date.min, d.b_sent_date or datetime.date.min))
# sadly we can't use the generic view because it only works with a queryset...
return render_to_response('idtracker/status_of_items.html', dict(object_list=drafts, title="IESG Status of Items"), context_instance=RequestContext(request))
queryset = IDInternal.objects.filter(primary_flag=1).exclude(cur_state__state__in=('RFC Ed Queue', 'RFC Published', 'AD is watching', 'Dead')).order_by('cur_state', 'status_date', 'ballot')
return object_list(request, template_name="idtracker/status_of_items.html", queryset=queryset, extra_context={'title': 'IESG Status of Items'})
def last_call(request):
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
drafts = list(IDInternal.objects.filter(states__type="draft-iesg", states__slug__in=('lc', 'writeupw', 'goaheadw')).distinct().order_by('states__order'))
drafts.sort(key=lambda d: (d.cur_state_id, d.status_date or datetime.date.min, d.b_sent_date or datetime.date.min))
# sadly we can't use the generic view because it only works with a queryset...
return render_to_response('idtracker/status_of_items.html', dict(object_list=drafts, title="Documents in Last Call", lastcall=1), context_instance=RequestContext(request))
queryset = IDInternal.objects.filter(primary_flag=1).filter(cur_state__state__in=('In Last Call', 'Waiting for Writeup', 'Waiting for AD Go-Ahead')).order_by('cur_state', 'status_date', 'ballot')
return object_list(request, template_name="idtracker/status_of_items.html", queryset=queryset, extra_context={'title': 'Documents in Last Call', 'lastcall': 1})
def redirect_id(request, object_id):
'''Redirect from historical document ID to preferred filename url.'''
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
raise Http404() # we don't store the numbers anymore
doc = get_object_or_404(InternetDraft, id_document_tag=object_id)
return HttpResponsePermanentRedirect("/doc/"+doc.filename+"/")
def redirect_rfc(request, rfc_number):
return HttpResponsePermanentRedirect("/doc/rfc"+rfc_number+"/")
def redirect_filename(request, filename):
return HttpResponsePermanentRedirect("/doc/"+filename+"/")
def redirect_ballot(request, object_id):
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
raise Http404() # we don't store the numbers anymore
ballot = get_object_or_404(BallotInfo, pk=object_id)
ids = ballot.drafts.filter(primary_flag=1)
if len(ids) == 0:
raise Http404("Ballot does not correspond to any document")
id = ids[0]
if id.rfc_flag:
return HttpResponsePermanentRedirect("/doc/rfc"+str(id.draft_id)+"/#ballot")
else:
return HttpResponsePermanentRedirect("/doc/"+id.draft.filename+"/#ballot")
def redirect_comment(request, object_id):
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
raise Http404() # we don't store the numbers anymore
comment = get_object_or_404(DocumentComment, pk=object_id)
id = comment.document
if id.rfc_flag:
return HttpResponsePermanentRedirect("/doc/rfc"+str(id.draft_id)+"/#history-"+str(object_id))
else:
return HttpResponsePermanentRedirect("/doc/"+id.draft.filename+"/#history-"+str(object_id))

View file

@ -227,7 +227,7 @@
| <a href="{% url ipr_search %}?option=document_search&amp;id={{ doc.name }}" rel="nofollow">IPR Disclosures</a>
| <a href="http://www.fenron.net/~fenner/ietf/deps/index.cgi?dep={{ name }}" rel="nofollow">Dependencies to this document</a>
| <a href="http://tools.ietf.org/idnits?url=http://tools.ietf.org/id/{{ doc.filename_with_rev }}" rel="nofollow" target="_blank">Check nits</a>
| <a href="/feed/comments/{{ name }}/">History feed</a>
| <a href="/feed/document-changes/{{ name }}/">History feed</a>
| <a href="http://www.google.com/search?as_q={{ doc.name }}&as_sitesearch={{ search_archive }}" rel="nofollow" target="_blank">Search Mailing Lists</a>
{% if user|has_role:"Area Director" %}
| <a href="https://www.iesg.org/bin/c5i?mid=6&rid=77&target={{ doc.name }}" rel="nofollow" target="_blank">Search Mailing Lists (ARO)</a>

View file

@ -6,7 +6,7 @@
{% block pagehead %}
<link rel="stylesheet" type="text/css" href="/css/doc.css"></link>
<link rel="alternate" type="application/atom+xml" href="/feed/comments/{{ doc.canonical_name }}/" />
<link rel="alternate" type="application/atom+xml" href="/feed/document-changes/{{ doc.canonical_name }}/" />
{% endblock %}
{% block content %}

View file

@ -1,3 +0,0 @@
{# Copyright The IETF Trust 2007, All Rights Reserved #}
{% load ietf_filters %}
{{ obj.comment_text|format_textarea|safe|truncatewords_html:"20" }}

View file

@ -1,5 +0,0 @@
{# Copyright The IETF Trust 2007, All Rights Reserved #}
{% load ietf_filters %}
[{{ obj.get_username }}] {{ obj.comment_text|removetags:"b"|truncatewords:"15"|safe }}
{% if obj.ballot %}[[ IESG {{ obj.get_ballot_display.upper }} ]]{% endif %}
{% if not obj.document.rfc_flag %}[ version {{ obj.version }} ]{% endif %}

View file

@ -1,3 +0,0 @@
{# Copyright The IETF Trust 2007, All Rights Reserved #}
{% load ietf_filters %}
{{ obj.ballot.last_call_text|escape|linebreaks }}

View file

@ -1,2 +0,0 @@
{# Copyright The IETF Trust 2007, All Rights Reserved #}
{{ obj }} ({{ obj.document.lc_sent_date|date:"F j" }}-{{ obj.document.lc_expiration_date|date:"F j, Y" }})

View file

@ -5,7 +5,7 @@ from django.conf.urls.defaults import patterns, include, handler404, handler500
from django.contrib import admin
from ietf.iesg.feeds import IESGAgenda
from ietf.idtracker.feeds import DocumentComments, InLastCall
from ietf.doc.feeds import DocumentChanges, InLastCall
from ietf.ipr.feeds import LatestIprDisclosures
from ietf.proceedings.feeds import LatestWgProceedingsActivity
from ietf.liaisons.feeds import Liaisons
@ -23,7 +23,7 @@ admin.site.disable_action('delete_selected')
feeds = {
'iesg-agenda': IESGAgenda,
'last-call': InLastCall,
'comments': DocumentComments,
'document-changes': DocumentChanges,
'group-changes': GroupChanges,
'ipr': LatestIprDisclosures,
'liaison': Liaisons,
@ -46,6 +46,7 @@ urlpatterns = patterns('',
(r'^cookies/', include('ietf.cookies.urls')),
(r'^doc/', include('ietf.idrfc.urls')),
(r'^drafts/', include('ietf.doc.redirect_drafts_urls')),
(r'^feed/comments/(?P<remainder>.*)/$', 'django.views.generic.simple.redirect_to', { 'url': '/feed/document-changes/%(remainder)s/'}),
(r'^feed/(?P<url>.*)/$', 'django.contrib.syndication.views.feed', { 'feed_dict': feeds}),
(r'^idtracker/', include('ietf.doc.redirect_idtracker_urls')),
(r'^iesg/', include('ietf.iesg.urls')),