Skip to content

Commit 8869468

Browse files
committed
New script bin/abstracts.py, intended to be run as a cronjob, to generate the ID abstracts files. Merged in from Jelte.
- Legacy-Id: 1598
1 parent 3879ac0 commit 8869468

6 files changed

Lines changed: 328 additions & 1 deletion

File tree

ietf/bin/abstracts.py

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
#!/usr/bin/env python
2+
from django.conf import settings
3+
from django.template.loader import render_to_string
4+
from ietf.idtracker.models import InternetDraft, Area, Acronym, AreaGroup, IETFWG, IDAuthor
5+
import sys, os, getopt, re
6+
7+
def group_string(group):
8+
text = group.group_acronym.name + " (" + group.group_acronym.acronym + ")"
9+
return text
10+
11+
def dashes_for_string(string):
12+
return len(string) * "-"
13+
14+
def draft_authors(draft):
15+
authors = IDAuthor.objects.filter(document=draft).order_by('author_order')
16+
author_names = []
17+
for author in authors:
18+
author_names.append(author.person.first_name + " " + author.person.last_name)
19+
return ", ".join(author_names)
20+
21+
def draft_title_text(draft):
22+
title = "\"" + draft.title + "\""
23+
return title
24+
25+
def rewrap(text, width=72, indent=0):
26+
paras = text.strip().split("\n\n")
27+
lwidth = width - indent
28+
join_str = "\n" + " " * indent
29+
for i in range(len(paras)):
30+
para = paras[i]
31+
while re.search("([^\n]{%s,}?) +"%lwidth, para):
32+
para = re.sub("([^\n]{%s,}?) +([^\n ]*)(\n|$)"%lwidth, "\g<1>\n\g<2> ", para)
33+
paras[i] = join_str + join_str.join(para.split('\n'))
34+
text = "\n\n".join(paras)
35+
return text
36+
37+
def tounix(text):
38+
# split into dos or mac lines.
39+
# (This is a no-op if the text is already unix text)
40+
def nlstrip(line):
41+
if line.startswith("\n"):
42+
return line[1:]
43+
else:
44+
return line
45+
lines = text.split("\r")
46+
lines = [ lines[0] ] + [ nlstrip(line) for line in lines[1:] ]
47+
return "\n".join(lines)
48+
49+
def wrap_and_indent(text, width=74, indent=0):
50+
result = []
51+
cur_line_words = []
52+
words = text.split()
53+
cur_len = 0
54+
for word in words:
55+
if cur_len + len(word) + indent < width:
56+
cur_line_words.append(word)
57+
cur_len = cur_len + len(word) + 1
58+
else:
59+
result.append(indent*" " + " ".join(cur_line_words))
60+
cur_line_words = [word]
61+
cur_len = len(word) + 1
62+
if len(cur_line_words) > 0:
63+
result.append(indent*" " + " ".join(cur_line_words))
64+
return "\n".join(result)
65+
66+
def draft_abstract_text(draft):
67+
# this function does nothing at the moment,
68+
# but cleanup functionality on the abstract
69+
# text should go here (like removing ^M etc)
70+
return rewrap(tounix(draft.abstract), 72, 4)
71+
72+
# sort key for the output group List, as the database model
73+
# does not seem to easily allow sorting by acronym
74+
def group_sort_key(group_elements):
75+
return group_elements['acronym']
76+
77+
# if txt_filename is not None, .txt output will be written to
78+
# that file
79+
# if idindex_filename is not None, idlist .txt output will be written to
80+
# that file
81+
# if html_filename is not None (eg. 1id_abstracts.html), an overview
82+
# will be written to this file
83+
# if html_directory is not None, html files per group will
84+
# be created in this directory, and an overview will be
85+
def create_abstracts_text(acronym, idindex_filename, txt_filename, html_filename, html_directory, silent=False):
86+
# if you want to store everythinh in a string instead of printing,
87+
# remember not to use str + str, but make a list for it and use join()
88+
if acronym:
89+
groups = IETFWG.objects.filter(areagroup__area__area_acronym__acronym=acronym).order_by('group_acronym')
90+
if len(groups) == 0:
91+
print "Error: unknown area acronym or area has no groups"
92+
sys.exit()
93+
else:
94+
groups = IETFWG.objects.all();
95+
96+
group_elements = []
97+
98+
for group in groups:
99+
if not silent:
100+
print group.group_acronym.acronym
101+
102+
drafts = group.active_drafts()
103+
104+
if len(drafts) > 0:
105+
group_text = group_string(group)
106+
107+
draft_elements = []
108+
109+
for draft in drafts:
110+
title_text = draft_title_text(draft)
111+
authors_text = draft_authors(draft)
112+
abstract_text = draft_abstract_text(draft)
113+
114+
title_parts = []
115+
title_parts.append(title_text)
116+
title_parts.append(authors_text)
117+
title_parts.append(str(draft.revision_date))
118+
title_parts.append("<" + draft.filename + "-" + draft.revision + ".txt" + ">")
119+
120+
# if wrap_and_indent is implemented as a template function
121+
# we wouldn't need the title_all here
122+
draft_elements.append({'title': title_text,
123+
'authors': authors_text,
124+
'rev_date': draft.revision_date,
125+
'filename': draft.filename + "-" + draft.revision + ".txt",
126+
'title_all': wrap_and_indent(", ".join(title_parts), 80, 2),
127+
'abstract': abstract_text
128+
#'abstract': wrap_and_indent(abstract_text, 80, 4)
129+
})
130+
131+
if html_directory:
132+
rel_url = html_directory + "/" + group.group_acronym.acronym + ".html"
133+
else:
134+
rel_url = ""
135+
136+
group_elements.append({'name': group_text,
137+
'dashes': dashes_for_string(group_text),
138+
'acronym': group.group_acronym.acronym,
139+
'rel_url': rel_url,
140+
'drafts': draft_elements,
141+
'active_draft_count': len(drafts)
142+
})
143+
144+
if html_directory:
145+
group_html_file = open(html_directory + os.sep + group.group_acronym.acronym + ".html", "w")
146+
group_html_file.write(render_to_string("idtracker/idtracker_abstracts_group.html", {'drafts': draft_elements}))
147+
group_html_file.close()
148+
149+
group_elements.sort(key=group_sort_key)
150+
if txt_filename:
151+
txt_file = open(txt_filename, "w")
152+
txt_file.write(render_to_string("idtracker/idtracker_abstracts.txt", {'groups': group_elements}))
153+
txt_file.close()
154+
155+
if idindex_filename:
156+
idindex_file = open(idindex_filename, "w")
157+
idindex_file.write(render_to_string("idtracker/idtracker_idlist.txt", {'groups': group_elements}))
158+
idindex_file.close()
159+
160+
if html_filename:
161+
html_file = open(html_filename, "w")
162+
html_file.write(render_to_string("idtracker/idtracker_abstracts.html", {'groups': group_elements}))
163+
html_file.close()
164+
165+
def usage():
166+
print "Usage: abstracts [OPTIONS]"
167+
print ""
168+
print "Options:"
169+
print ""
170+
print "-a, --area=<area>\tOnly handle groups and drafts from area acronym"
171+
print " \t(defaults to all)"
172+
print "-d, --htmldir=<dir>\tCreate group-specific html pages in dir"
173+
print "-f, --htmlfile=<file>\tWrite HTML index of groups to file"
174+
print "-h, --help\t\tShow this help"
175+
print "-i, --idindex=<file>\tCreate ID index txt list in file"
176+
print "-q, --silent\t\tDo not show progress"
177+
print "-t, --txtfile=<file>\tWrite abstract list to file"
178+
179+
def main():
180+
try:
181+
opts, args = getopt.getopt(sys.argv[1:], "a:d:f:hi:qt:", ["area=", "htmldir=", "htmlfile=", "help=", "idindex=", "silent=", "txtfile="])
182+
except getopt.GetoptError, err:
183+
# print help information and exit:
184+
print str(err) # will print something like "option -a not recognized"
185+
usage()
186+
sys.exit(2)
187+
188+
html_directory = None
189+
html_file = None
190+
idindex_file = None
191+
silent = False
192+
txt_file = None
193+
area_acronym = None
194+
195+
for o, a in opts:
196+
if o in ("-a", "--area"):
197+
area_acronym = a
198+
elif o in ("-d", "--htmldir"):
199+
html_directory = a
200+
elif o in ("-f", "--htmlfile"):
201+
html_file = a
202+
elif o in ("-h", "--help"):
203+
usage()
204+
sys.exit()
205+
elif o in ("-i", "--idindex"):
206+
idindex_file = a
207+
elif o in ("-q", "--silent"):
208+
silent = True
209+
elif o in ("-t", "--txtfile"):
210+
txt_file = a
211+
else:
212+
assert False, "Unrecognized option" + o
213+
214+
if (html_directory and not html_file) or not html_directory and html_file:
215+
print ""
216+
print "Error: when using one of -d and -f, the other must be used too"
217+
print ""
218+
usage()
219+
if (html_directory and html_file) or idindex_file or txt_file:
220+
if html_directory and not os.path.exists(html_directory):
221+
os.mkdir(html_directory)
222+
if html_directory and not os.path.isdir(html_directory):
223+
print "Error: ", html_directory, "exists, but is not a directory"
224+
sys.exit()
225+
create_abstracts_text(area_acronym, idindex_file, txt_file, html_file, html_directory, silent)
226+
else:
227+
print ""
228+
print "Error: either -t, -i or both -d and -f must be specified"
229+
print ""
230+
usage()
231+
sys.exit()
232+
233+
234+
if __name__ == "__main__":
235+
main()
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{% extends "base.html" %}
2+
3+
{% block content %}
4+
<h1>Current Internet-Drafts</h1>
5+
6+
<b>
7+
<p>
8+
This list and the associated sub-lists were generated on
9+
{% now "jS F Y"%}
10+
</p>
11+
<p>
12+
If you find errors, please notify
13+
<a href="mailto:internet-drafts@ietf.org">The I-D Administrator</a>.
14+
</p>
15+
</b>
16+
17+
<hr/>
18+
<p>
19+
Note that Internet-Drafts which are not associated with an
20+
IETF working group are collected into the "Individual Submissions"
21+
item at the bottom of the list.
22+
</p>
23+
<hr/>
24+
<p>
25+
This summary sheet provides a short synopsis of each Internet-Draft
26+
available within the "internet-drafts" directory at the shadow
27+
sites directory. These drafts are listed alphabetically by working
28+
group acronym and start date.
29+
</p>
30+
31+
<ul>
32+
{% for group in groups %}
33+
<li>
34+
<a href="{{ group.rel_url }}">{{ group.name }}</a>
35+
-- {{ group.active_draft_count }} Internet-Drafts
36+
</li>
37+
{% endfor %}
38+
</ul>
39+
40+
{% endblock %}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2+
Current Internet-Drafts
3+
This summary sheet provides a short synopsis of each Internet-Draft
4+
available within the \"internet-drafts\" directory at the shadow
5+
sites directory. These drafts are listed alphabetically by working
6+
group acronym and start date.
7+
8+
{% for group in groups %}
9+
{{ group.name }}
10+
{{ group.dashes }}
11+
12+
{% for draft in group.drafts %}
13+
{{ draft.title_all }}
14+
15+
{{ draft.abstract }}
16+
17+
{% endfor %}
18+
{% endfor %}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{% extends "base.html" %}
2+
3+
{% block content %}
4+
<h1>Current Internet-Drafts</h1>
5+
6+
{% for draft in drafts %}
7+
<p>
8+
<a href="http://www.ietf.org/internet-drafts/{{ draft.filename }}">
9+
{{ draft.title }},
10+
{{ draft.authors }},
11+
{{ draft.rev_date }}
12+
</a>
13+
</p>
14+
<p>
15+
{{ draft.abstract }}
16+
</p>
17+
{% endfor %}
18+
19+
{% endblock %}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
Current Internet-Drafts
3+
This summary sheet provides an index of each Internet-Draft.
4+
These drafts are listed alphabetically by Working Group acronym and
5+
initial post date.
6+
7+
{% for group in groups %}
8+
{{ group.name }}
9+
{{ group.dashes }}
10+
11+
{% for draft in group.drafts %}
12+
{{ draft.title_all }}
13+
14+
{% endfor %}
15+
{% endfor %}

ietf/templates/wginfo/wg-dir.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ <h2>{{ wg.area_acronym.name }}</h2>
4242
<li><a href="mailto:{{ ad.person.email.1|escape }}">{{ ad.person }} &lt;{{ ad.person.email.1 }}&gt;</a></li>
4343
{% endfor %}
4444
</ul>
45-
{% for url in wg.area.urls %}
45+
{% for url in wg.area.area.urls.all %}
4646
{% if forloop.first %}
4747
<p>Additional Area Information:</p>
4848
<ul>

0 commit comments

Comments
 (0)