Skip to content

Commit c233f07

Browse files
committed
Added a management command to generate draft bibxml files, and also a trial version of datatracker draft bibxml pages.
- Legacy-Id: 16962
1 parent bf299bb commit c233f07

7 files changed

Lines changed: 148 additions & 40 deletions

File tree

ietf/doc/factories.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class Meta:
3030
model = Document
3131

3232
title = factory.Faker('sentence',nb_words=5)
33+
abstract = factory.Faker('paragraph', nb_sentences=5)
3334
rev = '00'
3435
std_level_id = None # type: Optional[str]
3536
intended_std_level_id = None
Lines changed: 78 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,95 @@
1-
# Copyright The IETF Trust 2012-2019, All Rights Reserved
1+
# Copyright The IETF Trust 2018-2019, All Rights Reserved
22
# -*- coding: utf-8 -*-
33

4-
54
from __future__ import absolute_import, print_function, unicode_literals
65

6+
import datetime
77
import io
8-
import sys
98
import os
9+
import re
10+
import sys
1011

11-
from django.core.management.base import BaseCommand
1212
from django.conf import settings
13+
from django.core.management.base import BaseCommand
1314
from django.template.loader import render_to_string
1415

15-
from ietf.doc.models import Document
16-
17-
def write(fn, new):
18-
try:
19-
f = io.open(fn)
20-
old = f.read().decode('utf-8')
21-
f.close
22-
except IOError:
23-
old = ""
24-
if old.strip() != new.strip():
25-
sys.stdout.write(os.path.basename(fn)+'\n')
26-
f = io.open(fn, "wb")
27-
f.write(new.encode('utf-8'))
28-
f.close()
16+
import debug # pyflakes:ignore
17+
18+
from ietf.doc.models import NewRevisionDocEvent
19+
20+
DEFAULT_DAYS = 7
2921

3022
class Command(BaseCommand):
31-
help = ('Generate draft bibxml files, for xml2rfc references')
23+
help = ('Generate draft bibxml files for xml2rfc references, placing them in the '
24+
'directory configured in settings.BIBXML_BASE_PATH: %s. '
25+
'By default, generate files as needed for new draft revisions from the '
26+
'last %s days.' % (settings.BIBXML_BASE_PATH, DEFAULT_DAYS))
27+
28+
def add_arguments(self, parser):
29+
parser.add_argument('--all', action='store_true', default=False, help="Process all documents, not only recent submissions")
30+
parser.add_argument('--days', type=int, default=DEFAULT_DAYS, help="Look submissions from the last DAYS days, instead of %s" % DEFAULT_DAYS)
31+
32+
def say(self, msg):
33+
if self.verbosity > 0:
34+
sys.stdout.write(msg)
35+
sys.stdout.write('\n')
36+
37+
def note(self, msg):
38+
if self.verbosity > 1:
39+
sys.stdout.write(msg)
40+
sys.stdout.write('\n')
41+
42+
def mutter(self, msg):
43+
if self.verbosity > 2:
44+
sys.stdout.write(msg)
45+
sys.stdout.write('\n')
46+
47+
def write(self, fn, new):
48+
# normalize new
49+
new = re.sub(r'\r\n?', r'\n', new)
50+
try:
51+
with io.open(fn, encoding='utf-8') as f:
52+
old = f.read()
53+
except IOError:
54+
old = ""
55+
if old.strip() != new.strip():
56+
self.note('Writing %s' % os.path.basename(fn))
57+
with io.open(fn, "w", encoding='utf-8') as f:
58+
f.write(new)
3259

3360
def handle(self, *args, **options):
34-
documents = Document.objects.filter(type__slug='draft')
61+
self.verbosity = options.get("verbosity", 1)
62+
process_all = options.get("all")
63+
days = options.get("days")
64+
#
3565
bibxmldir = os.path.join(settings.BIBXML_BASE_PATH, 'bibxml3')
3666
if not os.path.exists(bibxmldir):
3767
os.makedirs(bibxmldir)
38-
for doc in documents:
39-
ref_text = render_to_string('doc/bibxml.xml', {'doc': doc, 'doc_bibtype':'I-D'})
40-
ref_file_name = os.path.join(bibxmldir, 'reference.I-D.%s.xml' % (doc.name, ))
41-
ref_rev_file_name = os.path.join(bibxmldir, 'reference.I-D.%s-%s.xml' % (doc.name, doc.rev))
42-
write(ref_file_name, ref_text)
43-
write(ref_rev_file_name, ref_text)
44-
68+
#
69+
if process_all:
70+
doc_events = NewRevisionDocEvent.objects.filter(type='new_revision', doc__type_id='draft')
71+
else:
72+
start = datetime.datetime.now() - datetime.timedelta(days=days)
73+
doc_events = NewRevisionDocEvent.objects.filter(type='new_revision', doc__type_id='draft', time__gte=start)
74+
doc_events = doc_events.order_by('time')
75+
76+
for e in doc_events:
77+
self.mutter('%s %s' % (e.time, e.doc.name))
78+
try:
79+
e.doc.date = e.time.date()
80+
doc = e.doc
81+
if e.rev != doc.rev:
82+
for h in doc.history_set.order_by("-time"):
83+
if e.rev == h.rev:
84+
doc = h
85+
break
86+
ref_text = '%s' % render_to_string('doc/bibxml.xml', {'doc': doc, 'doc_bibtype':'I-D'})
87+
if e.rev == e.doc.rev:
88+
ref_file_name = os.path.join(bibxmldir, 'reference.I-D.%s.xml' % (doc.name[6:], ))
89+
self.write(ref_file_name, ref_text)
90+
else:
91+
self.note("Skipping %s; outdated revision: %s" % (os.path.basename(ref_file_name), e.rev))
92+
ref_rev_file_name = os.path.join(bibxmldir, 'reference.I-D.%s-%s.xml' % (doc.name, doc.rev))
93+
self.write(ref_rev_file_name, ref_text)
94+
except Exception as ee:
95+
sys.stderr.write('\n%s-%s: %s\n' % (doc.name, doc.rev, ee))

ietf/doc/tests.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import shutil
99
import datetime
1010
import io
11+
import lxml
1112
import sys
1213
import bibtexparser
1314

@@ -46,6 +47,7 @@
4647
from ietf.utils.mail import outbox
4748
from ietf.utils.test_utils import login_testing_unauthorized, unicontent
4849
from ietf.utils.test_utils import TestCase
50+
from ietf.utils.text import normalize_text
4951

5052
class SearchTests(TestCase):
5153
def test_search(self):
@@ -972,6 +974,22 @@ def test_document_bibtex(self):
972974
#
973975
self.assertNotIn('doi', entry)
974976

977+
def test_document_bibxml(self):
978+
979+
draft = IndividualDraftFactory.create()
980+
docname = '%s-%s' % (draft.name, draft.rev)
981+
url = urlreverse('ietf.doc.views_doc.document_bibxml', kwargs=dict(name=draft.name))
982+
r = self.client.get(url)
983+
entry = lxml.etree.fromstring(r.content)
984+
self.assertEqual(entry.find('./front/title').text, draft.title)
985+
date = entry.find('./front/date')
986+
self.assertEqual(date.get('year'), str(draft.pub_date().year))
987+
self.assertEqual(date.get('month'), draft.pub_date().strftime('%B'))
988+
self.assertEqual(date.get('day'), str(draft.pub_date().day))
989+
self.assertEqual(normalize_text(entry.find('./front/abstract/t').text), normalize_text(draft.abstract))
990+
self.assertEqual(entry.find('./seriesInfo').get('value'), docname)
991+
self.assertEqual(entry.find('./seriesInfo[@name="DOI"]'), None)
992+
975993
class AddCommentTestCase(TestCase):
976994
def test_add_comment(self):
977995
draft = WgDraftFactory(name='draft-ietf-mars-test',group__acronym='mars')

ietf/doc/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474

7575
url(r'^%(name)s(?:/%(rev)s)?/$' % settings.URL_REGEXPS, views_doc.document_main),
7676
url(r'^%(name)s(?:/%(rev)s)?/bibtex/$' % settings.URL_REGEXPS, views_doc.document_bibtex),
77+
url(r'^bibxml3/%(name)s(?:-%(rev)s)?.xml$' % settings.URL_REGEXPS, views_doc.document_bibxml),
7778
url(r'^%(name)s/history/$' % settings.URL_REGEXPS, views_doc.document_history),
7879
url(r'^%(name)s/writeup/$' % settings.URL_REGEXPS, views_doc.document_writeup),
7980
url(r'^%(name)s/email/$' % settings.URL_REGEXPS, views_doc.document_email),

ietf/doc/views_doc.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -824,7 +824,37 @@ def document_bibtex(request, name, rev=None):
824824
latest_revision=latest_revision,
825825
doi=doi,
826826
),
827-
content_type="text/plain; charset=utf-8",
827+
content_type="application/xml; charset=utf-8",
828+
)
829+
830+
831+
def document_bibxml(request, name, rev=None):
832+
# This only deals with drafts, as bibxml entries for RFCs should come from
833+
# the RFC-Editor.
834+
doc = get_object_or_404(Document, docalias__name=name, name__startswith='draft-', type_id='draft')
835+
836+
latest_revision = doc.latest_event(NewRevisionDocEvent, type="new_revision")
837+
latest_rev = latest_revision.rev if latest_revision else None
838+
839+
if rev != None and rev != doc.rev:
840+
# find the entry in the history
841+
for h in doc.history_set.order_by("-time"):
842+
if rev == h.rev:
843+
doc = h
844+
break
845+
846+
try:
847+
doc_event = NewRevisionDocEvent.objects.get(doc__name=doc.name, rev=(rev or latest_rev))
848+
doc.date = doc_event.time.date()
849+
except DocEvent.DoesNotExist:
850+
doc.date = doc.time.date() # Even if this may be incoreect, what would be better?
851+
852+
return render(request, "doc/bibxml.xml",
853+
dict(
854+
doc=doc,
855+
doc_bibtype='I-D',
856+
),
857+
content_type="application/xml; charset=utf-8",
828858
)
829859

830860

ietf/templates/doc/bibxml.xml

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
1-
<?xml version='1.0' encoding='UTF-8'?>
2-
<reference anchor='{{doc_bibtype}}.{{doc.name|slice:"6:"}}'>
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<reference anchor="{{doc_bibtype}}.{{doc.name|slice:"6:"}}">
33
<front>
4-
<title>{{doc.title}}</title>
5-
{% for author in doc.documentauthor_set.all %}
6-
<author initials='{{ author.person.initials }}' surname='{{ author.person.last_name }}' fullname='{{ author.person.name }}'>
7-
<organization>{{ author.affiliation }}</organization>
8-
</author>
9-
{% endfor %}
10-
<date month='{{doc.time|date:"F"}}' day='{{doc.time.day}}' year='{{doc.time.year}}' />
11-
<abstract><t>{{doc.abstract}}</t></abstract>
4+
<title>{{doc.title}}</title>{% if doc.submission %}{% for author in doc.submission.authors %}
5+
<author fullname="{{ author.name }}">
6+
{% if author.affiliation %}<organization>{{ author.affiliation }}</organization>
7+
{% endif %}</author>{% endfor %}{% else %}{% for author in doc.documentauthor_set.all %}
8+
<author initials="{{ author.person.initials }}" surname="{{ author.person.last_name }}" fullname="{{ author.person.name }}">
9+
{% if author.affiliation %}<organization>{{ author.affiliation }}</organization>
10+
{% endif %}</author>{% endfor %}{% endif %}
11+
<date month="{{doc.date|date:"F"}}" day="{{doc.date.day}}" year="{{doc.date.year}}" />
12+
<abstract>
13+
<t>{{doc.abstract}}
14+
</t>
15+
</abstract>
1216
</front>
13-
<seriesInfo name='Internet-Draft' value='{{doc.name}}-{{doc.rev}}' />
14-
<format type='TXT' target='https://www.ietf.org/internet-drafts/{{doc.name}}-{{doc.rev}}.txt' />
17+
<seriesInfo name="Internet-Draft" value="{{doc.name}}-{{doc.rev}}" />
18+
{% if doi %}<seriesInfo name="DOI" value="{{doi}}" />
19+
{% endif %}<format type="TXT" target="https://www.ietf.org/internet-drafts/{{doc.name}}-{{doc.rev}}.txt" />
1520
</reference>

ietf/utils/text.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,3 +194,5 @@ def texescape(s):
194194
def unwrap(s):
195195
return s.replace('\n', ' ')
196196

197+
def normalize_text(s):
198+
return s.replace(r'\s+', ' ').strip()

0 commit comments

Comments
 (0)