Added a simple page to show release information parsed from a release's changelog file.
- Legacy-Id: 4958
This commit is contained in:
parent
7f42117210
commit
bfe0756351
66
changelog.py
Normal file
66
changelog.py
Normal file
|
@ -0,0 +1,66 @@
|
|||
import re
|
||||
from tzparse import tzparse
|
||||
from datetime import datetime as Datetime
|
||||
|
||||
def parse_date(dstr):
|
||||
formats = [
|
||||
"%d %b %Y %H:%M:%S %Z", # standard logfile format
|
||||
"%d %b %Y %H:%M:%S",
|
||||
"%d %b %Y %H:%M %Z",
|
||||
"%d %b %Y %H:%M",
|
||||
"%d %b %Y %Z",
|
||||
"%Y-%m-%d %H:%M:%S %Z",
|
||||
"%Y-%m-%d %H:%M:%S",
|
||||
"%Y-%m-%d_%H:%M:%S %Z",
|
||||
"%Y-%m-%d_%H:%M:%S",
|
||||
"%Y-%m-%dT%H:%M:%S%Z",
|
||||
"%Y-%m-%dT%H:%M:%S",
|
||||
"%Y-%m-%d %H:%M %Z",
|
||||
"%Y-%m-%d %H:%M",
|
||||
"%Y-%m-%d",
|
||||
]
|
||||
for format in formats:
|
||||
try:
|
||||
t = tzparse(dstr, format)
|
||||
return t
|
||||
except Exception:
|
||||
pass
|
||||
raise Exception("Couldn't parse the date string '%s'" % dstr)
|
||||
|
||||
class ChangeLogEntry:
|
||||
package = ""
|
||||
version = ""
|
||||
logentry = ""
|
||||
author = ""
|
||||
email = ""
|
||||
date = ""
|
||||
time = ""
|
||||
|
||||
def parse(logfile):
|
||||
ver_line = "^(\w+) \((\S+)\) (\S+;)? (?:urgency=(\S+))?$"
|
||||
sig_line = "^ -- ([^<]+) <([^>]+)> (.*?) *$"
|
||||
|
||||
entries = []
|
||||
if type(logfile) == type(''):
|
||||
logfile = open(logfile)
|
||||
entry = None
|
||||
for line in logfile:
|
||||
if re.match(ver_line, line):
|
||||
package, version, distribution, urgency = re.match(ver_line, line).groups()
|
||||
entry = ChangeLogEntry()
|
||||
entry.package = package
|
||||
entry.version = version
|
||||
entry.logentry = ""
|
||||
elif re.match(sig_line, line):
|
||||
author, email, date = re.match(sig_line, line).groups()
|
||||
entry.author = author
|
||||
entry.email = email
|
||||
entry.date = date
|
||||
entry.time = parse_date(date)
|
||||
entry.logentry = entry.logentry.rstrip()
|
||||
entries += [ entry ]
|
||||
elif entry:
|
||||
entry.logentry += line
|
||||
else:
|
||||
print "Unexpected line: '%s'" % line
|
||||
return entries
|
0
ietf/release/__init__.py
Normal file
0
ietf/release/__init__.py
Normal file
1
ietf/release/models.py
Normal file
1
ietf/release/models.py
Normal file
|
@ -0,0 +1 @@
|
|||
# This app has no models
|
16
ietf/release/tests.py
Normal file
16
ietf/release/tests.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
"""
|
||||
This file demonstrates writing tests using the unittest module. These will pass
|
||||
when you run "manage.py test".
|
||||
|
||||
Replace this with more appropriate tests for your application.
|
||||
"""
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
|
||||
class SimpleTest(TestCase):
|
||||
def test_basic_addition(self):
|
||||
"""
|
||||
Tests that 1 + 1 always equals 2.
|
||||
"""
|
||||
self.assertEqual(1 + 1, 2)
|
22
ietf/release/views.py
Normal file
22
ietf/release/views.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
import re
|
||||
import os
|
||||
|
||||
from django.template import RequestContext
|
||||
from django.shortcuts import render_to_response
|
||||
|
||||
import changelog
|
||||
|
||||
def release(request, version=None):
|
||||
entries = {}
|
||||
log_entries = changelog.parse("changelog")
|
||||
next = None
|
||||
for entry in log_entries:
|
||||
if next:
|
||||
next.prev = entry
|
||||
entry.next = next
|
||||
next = entry
|
||||
entries = dict([ (entry.version, entry) for entry in log_entries])
|
||||
if version == None:
|
||||
version = log_entries[0].version
|
||||
return render_to_response('release/release.html', { 'entry': entries[version], }, context_instance=RequestContext(request))
|
||||
|
23
ietf/templates/release/release.html
Normal file
23
ietf/templates/release/release.html
Normal file
|
@ -0,0 +1,23 @@
|
|||
{% extends "registration/base.html" %}
|
||||
|
||||
{% block title %}Release information{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="release">
|
||||
<h2>Release {{ entry.version }}, released {{ entry.date }}</h2>
|
||||
<p style="font-size: 90%">
|
||||
{% if entry.prev %}← <a href="/release/{{entry.prev.version}}/">previous release</a>{% else %}<span style="color: grey">← previous release</span>{% endif %}
|
||||
|
|
||||
{% if entry.next %}<a href="/release/{{entry.next.version}}/">next release</a> →{% else %}<span style="color: grey">next release →</span>{% endif %}
|
||||
</p>
|
||||
<p>
|
||||
<b>Release Notes:</b>
|
||||
<tt>
|
||||
<pre>
|
||||
{{entry.logentry}}
|
||||
</pre>
|
||||
</tt>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
36
ietf/urls.py
36
ietf/urls.py
|
@ -43,33 +43,31 @@ if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
|||
del sitemaps['drafts'] # not needed, overlaps sitemaps['idtracker']
|
||||
|
||||
urlpatterns = patterns('',
|
||||
(r'^feed/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',
|
||||
{ 'feed_dict': feeds}),
|
||||
(r'^sitemap.xml$', 'django.contrib.sitemaps.views.index',
|
||||
{ 'sitemaps': sitemaps}),
|
||||
(r'^sitemap-(?P<section>.+).xml$', 'django.contrib.sitemaps.views.sitemap',
|
||||
{'sitemaps': sitemaps}),
|
||||
(r'^$', 'ietf.idrfc.views.main'),
|
||||
(r'^accounts/', include('ietf.ietfauth.urls')),
|
||||
(r'^admin/', include(admin.site.urls)),
|
||||
(r'^admin/doc/', include('django.contrib.admindocs.urls')),
|
||||
(r'^ann/', include('ietf.announcements.urls')),
|
||||
(r'^idtracker/', include('ietf.idtracker.urls')),
|
||||
(r'^community/', include('ietf.community.urls')),
|
||||
(r'^cookies/', include('ietf.cookies.urls')),
|
||||
(r'^doc/', include('ietf.idrfc.urls')),
|
||||
(r'^drafts/', include('ietf.idindex.urls')),
|
||||
(r'^feed/(?P<url>.*)/$', 'django.contrib.syndication.views.feed', { 'feed_dict': feeds}),
|
||||
(r'^idtracker/', include('ietf.idtracker.urls')),
|
||||
(r'^iesg/', include('ietf.iesg.urls')),
|
||||
(r'^ipr/', include('ietf.ipr.urls')),
|
||||
(r'^liaison/', include('ietf.liaisons.urls')),
|
||||
(r'^list/', include('ietf.mailinglists.urls')),
|
||||
(r'^(?P<path>public)/', include('ietf.redirects.urls')),
|
||||
(r'^ipr/', include('ietf.ipr.urls')),
|
||||
(r'^meeting/', include('ietf.meeting.urls')),
|
||||
(r'^accounts/', include('ietf.ietfauth.urls')),
|
||||
(r'^doc/', include('ietf.idrfc.urls')),
|
||||
(r'^wg/', include('ietf.wginfo.urls')),
|
||||
(r'^cookies/', include('ietf.cookies.urls')),
|
||||
(r'^person/', include('ietf.person.urls')),
|
||||
(r'^submit/', include('ietf.submit.urls')),
|
||||
(r'^release/$', 'ietf.release.views.release'),
|
||||
(r'^release/(?P<version>.+)/$', 'ietf.release.views.release'),
|
||||
(r'^sitemap-(?P<section>.+).xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}),
|
||||
(r'^sitemap.xml$', 'django.contrib.sitemaps.views.index', { 'sitemaps': sitemaps}),
|
||||
(r'^streams/', include('ietf.ietfworkflows.urls')),
|
||||
(r'^community/', include('ietf.community.urls')),
|
||||
|
||||
(r'^$', 'ietf.idrfc.views.main'),
|
||||
(r'^admin/doc/', include('django.contrib.admindocs.urls')),
|
||||
('^admin/', include(admin.site.urls)),
|
||||
(r'^submit/', include('ietf.submit.urls')),
|
||||
(r'^(?P<path>public)/', include('ietf.redirects.urls')),
|
||||
(r'^wg/', include('ietf.wginfo.urls')),
|
||||
|
||||
# Google webmaster tools verification url
|
||||
(r'^googlea30ad1dacffb5e5b.html', 'django.views.generic.simple.direct_to_template', { 'template': 'googlea30ad1dacffb5e5b.html' }),
|
||||
|
|
Loading…
Reference in a new issue