Skip to content

Commit 14a8e3c

Browse files
committed
Merged in [19262] [19263] [19264] [19265] from rjsparks@nostrum.com:
Provide replacements for idnits2's internal use of tools.ietf.org: - representation of obsoleted RFCs - rfc-status blob - minimal per-document .status files - Legacy-Id: 19276 Note: SVN reference [19262] has been migrated to Git commit 3283645 Note: SVN reference [19263] has been migrated to Git commit b179143 Note: SVN reference [19264] has been migrated to Git commit d283b96 Note: SVN reference [19265] has been migrated to Git commit 1eb4636
2 parents e595415 + 1eb4636 commit 14a8e3c

10 files changed

Lines changed: 225 additions & 0 deletions

File tree

bin/hourly

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ mv $TMPFILE9 $DERIVED/1id-index.txt
8585
mv $TMPFILEA $DERIVED/1id-abstracts.txt
8686
mv $TMPFILEB $DERIVED/all_id2.txt
8787

88+
$DTDIR/ietf/manage.py generate_idnits2_rfc_status
89+
$DTDIR/ietf/manage.py generate_idnits2_rfcs_obsoleted
8890

8991
CHARTER=/a/www/ietf-ftp/charter
9092
wget -q https://datatracker.ietf.org/wg/1wg-charters-by-acronym.txt -O $CHARTER/1wg-charters-by-acronym.txt
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Copyright The IETF Trust 2021 All Rights Reserved
2+
3+
import os
4+
5+
from django.conf import settings
6+
from django.core.management.base import BaseCommand
7+
8+
from ietf.doc.utils import generate_idnits2_rfc_status
9+
from ietf.utils.log import log
10+
11+
class Command(BaseCommand):
12+
help = ('Generate the rfc_status blob used by idnits2')
13+
14+
def handle(self, *args, **options):
15+
filename=os.path.join(settings.DERIVED_DIR,'idnits2-rfc-status')
16+
blob = generate_idnits2_rfc_status()
17+
try:
18+
bytes = blob.encode('utf-8')
19+
with open(filename,'wb') as f:
20+
f.write(bytes)
21+
except Exception as e:
22+
log('failed to write idnits2-rfc-status: '+str(e))
23+
raise e
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Copyright The IETF Trust 2021 All Rights Reserved
2+
3+
import os
4+
5+
from django.conf import settings
6+
from django.core.management.base import BaseCommand
7+
8+
from ietf.doc.utils import generate_idnits2_rfcs_obsoleted
9+
from ietf.utils.log import log
10+
11+
class Command(BaseCommand):
12+
help = ('Generate the rfcs-obsoleted file used by idnits2')
13+
14+
def handle(self, *args, **options):
15+
filename=os.path.join(settings.DERIVED_DIR,'idnits2-rfcs-obsoleted')
16+
blob = generate_idnits2_rfcs_obsoleted()
17+
try:
18+
bytes = blob.encode('utf-8')
19+
with open(filename,'wb') as f:
20+
f.write(bytes)
21+
except Exception as e:
22+
log('failed to write idnits2-rfcs-obsoleted: '+str(e))
23+
raise e

ietf/doc/tests.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2377,3 +2377,61 @@ def test_markdown_and_text(self):
23772377
self.assertEqual(r.status_code,200)
23782378
q = PyQuery(r.content)
23792379
self.assertEqual(q('#materials-content .panel-body a').attr['href'],'https://unusual.example')
2380+
2381+
class Idnits2SupportTests(TestCase):
2382+
2383+
def setUp(self):
2384+
self.derived_dir = self.tempdir('derived')
2385+
self.saved_derived_dir = settings.DERIVED_DIR
2386+
settings.DERIVED_DIR = self.derived_dir
2387+
2388+
def tearDown(self):
2389+
settings.DERIVED_DIR = self.saved_derived_dir
2390+
shutil.rmtree(self.derived_dir)
2391+
2392+
def test_obsoleted(self):
2393+
rfc = WgRfcFactory(alias2__name='rfc1001')
2394+
WgRfcFactory(alias2__name='rfc1003',relations=[('obs',rfc)])
2395+
rfc = WgRfcFactory(alias2__name='rfc1005')
2396+
WgRfcFactory(alias2__name='rfc1007',relations=[('obs',rfc)])
2397+
2398+
url = urlreverse('ietf.doc.views_doc.idnits2_rfcs_obsoleted')
2399+
r = self.client.get(url)
2400+
self.assertEqual(r.status_code, 404)
2401+
call_command('generate_idnits2_rfcs_obsoleted')
2402+
url = urlreverse('ietf.doc.views_doc.idnits2_rfcs_obsoleted')
2403+
r = self.client.get(url)
2404+
self.assertEqual(r.status_code, 200)
2405+
self.assertEqual(r.content, b'1001 1003\n1005 1007\n')
2406+
2407+
def test_rfc_status(self):
2408+
for slug in ('bcp', 'ds', 'exp', 'hist', 'inf', 'std', 'ps', 'unkn'):
2409+
WgRfcFactory(std_level_id=slug)
2410+
url = urlreverse('ietf.doc.views_doc.idnits2_rfc_status')
2411+
r = self.client.get(url)
2412+
self.assertEqual(r.status_code,404)
2413+
call_command('generate_idnits2_rfc_status')
2414+
r = self.client.get(url)
2415+
self.assertEqual(r.status_code,200)
2416+
blob = unicontent(r).replace('\n','')
2417+
self.assertEqual(blob[6312-1],'O')
2418+
2419+
def test_idnits2_state(self):
2420+
rfc = WgRfcFactory()
2421+
url = urlreverse('ietf.doc.views_doc.idnits2_state', kwargs=dict(name=rfc.canonical_name()))
2422+
r = self.client.get(url)
2423+
self.assertEqual(r.status_code, 200)
2424+
self.assertContains(r,'rfcnum')
2425+
2426+
draft = WgDraftFactory()
2427+
url = urlreverse('ietf.doc.views_doc.idnits2_state', kwargs=dict(name=draft.canonical_name()))
2428+
r = self.client.get(url)
2429+
self.assertEqual(r.status_code, 200)
2430+
self.assertNotContains(r,'rfcnum')
2431+
self.assertContains(r,'Unknown')
2432+
2433+
draft = WgDraftFactory(intended_std_level_id='ps')
2434+
url = urlreverse('ietf.doc.views_doc.idnits2_state', kwargs=dict(name=draft.canonical_name()))
2435+
r = self.client.get(url)
2436+
self.assertEqual(r.status_code, 200)
2437+
self.assertContains(r,'Proposed')

ietf/doc/urls.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@
6969
url(r'^html/(?P<name>std[0-9]+?)(\.txt|\.html)?/?$', RedirectView.as_view(url=settings.RFC_EDITOR_INFO_BASE_URL+"%(name)s", permanent=False)),
7070
url(r'^html/%(name)s(?:-%(rev)s)?(\.txt|\.html)?/?$' % settings.URL_REGEXPS, views_doc.document_html),
7171
url(r'^html/(?P<name>[Rr][Ff][Cc] [0-9]+?)(\.txt|\.html)?/?$', views_doc.document_html),
72+
url(r'^idnits2-rfcs-obsoleted/?$', views_doc.idnits2_rfcs_obsoleted),
73+
url(r'^idnits2-rfc-status/?$', views_doc.idnits2_rfc_status),
7274

7375
url(r'^all/?$', views_search.index_all_drafts),
7476
url(r'^active/?$', views_search.index_active_drafts),
@@ -78,6 +80,7 @@
7880

7981
url(r'^%(name)s(?:/%(rev)s)?/$' % settings.URL_REGEXPS, views_doc.document_main),
8082
url(r'^%(name)s(?:/%(rev)s)?/bibtex/$' % settings.URL_REGEXPS, views_doc.document_bibtex),
83+
url(r'^%(name)s(?:/%(rev)s)?/idnits2-state/$' % settings.URL_REGEXPS, views_doc.idnits2_state),
8184
url(r'^bibxml3/reference.I-D.%(name)s(?:-%(rev)s)?.xml$' % settings.URL_REGEXPS, views_doc.document_bibxml_ref),
8285
url(r'^bibxml3/%(name)s(?:-%(rev)s)?.xml$' % settings.URL_REGEXPS, views_doc.document_bibxml),
8386
url(r'^%(name)s/history/$' % settings.URL_REGEXPS, views_doc.document_history),

ietf/doc/utils.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,19 @@
99
import math
1010
import os
1111
import re
12+
import textwrap
1213

1314
from collections import defaultdict
1415
from urllib.parse import quote
1516

1617
from django.conf import settings
1718
from django.contrib import messages
1819
from django.forms import ValidationError
20+
from django.template.loader import render_to_string
1921
from django.utils.html import escape
2022
from django.urls import reverse as urlreverse
2123

24+
2225
import debug # pyflakes:ignore
2326
from ietf.community.models import CommunityList
2427
from ietf.community.utils import docs_tracked_by_community_list
@@ -1232,3 +1235,54 @@ def update_doc_extresources(doc, new_resources, by):
12321235
e.save()
12331236
doc.save_with_history([e])
12341237
return True
1238+
1239+
def generate_idnits2_rfc_status():
1240+
1241+
blob=['N']*10000
1242+
1243+
symbols={
1244+
'ps': 'P',
1245+
'inf': 'I',
1246+
'exp': 'E',
1247+
'ds': 'D',
1248+
'hist': 'H',
1249+
'std': 'S',
1250+
'bcp': 'B',
1251+
'unkn': 'U',
1252+
}
1253+
1254+
rfcs = Document.objects.filter(type_id='draft',states__slug='rfc',states__type='draft')
1255+
for rfc in rfcs:
1256+
offset = int(rfc.rfcnum)-1
1257+
blob[offset] = symbols[rfc.std_level_id]
1258+
if rfc.related_that('obs'):
1259+
blob[offset] = 'O'
1260+
1261+
# Workarounds for unusual states in the datatracker
1262+
1263+
# Document.get(docalias='rfc6312').rfcnum == 6342
1264+
# 6312 was published with the wrong rfc number in it
1265+
# weird workaround in the datatracker - there are two
1266+
# DocAliases starting with rfc - the canonical name code
1267+
# searches for the lexically highest alias starting with rfc
1268+
# which is getting lucky.
1269+
blob[6312 - 1] = 'O'
1270+
1271+
# RFC200 is an old RFC List by Number
1272+
blob[200 -1] = 'O'
1273+
1274+
# End Workarounds
1275+
1276+
blob = re.sub('N*$','',''.join(blob))
1277+
blob = textwrap.fill(blob, width=64)
1278+
1279+
return blob
1280+
1281+
def generate_idnits2_rfcs_obsoleted():
1282+
obsdict = defaultdict(list)
1283+
for r in RelatedDocument.objects.filter(relationship_id='obs'):
1284+
obsdict[int(r.target.document.rfc_number())].append(int(r.source.rfc_number()))
1285+
for k in obsdict:
1286+
obsdict[k] = sorted(obsdict[k])
1287+
return render_to_string('doc/idnits2-rfcs-obsoleted.txt', context={'obsitems':sorted(obsdict.items())})
1288+

ietf/doc/views_doc.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
from django.conf import settings
5252
from django import forms
5353

54+
5455
import debug # pyflakes:ignore
5556

5657
from ietf.doc.models import ( Document, DocAlias, DocHistory, DocEvent, BallotDocEvent, BallotType,
@@ -79,6 +80,7 @@
7980
from ietf.review.utils import can_request_review_of_doc, review_assignments_to_list_for_docs
8081
from ietf.review.utils import no_review_from_teams_on_doc
8182
from ietf.utils import markup_txt, log
83+
from ietf.utils.draft import Draft
8284
from ietf.utils.response import permission_denied
8385
from ietf.utils.text import maybe_split
8486

@@ -1714,3 +1716,54 @@ def all_presentations(request, name):
17141716
'in_progress': in_progress,
17151717
'past' : past+recent,
17161718
})
1719+
1720+
1721+
def idnits2_rfcs_obsoleted(request):
1722+
filename = os.path.join(settings.DERIVED_DIR,'idnits2-rfcs-obsoleted')
1723+
try:
1724+
with open(filename,'rb') as f:
1725+
blob = f.read()
1726+
return HttpResponse(blob,content_type='text/plain;charset=utf-8')
1727+
except Exception as e:
1728+
log.log('Failed to read idnits2-rfcs-obsoleted:'+str(e))
1729+
raise Http404
1730+
1731+
1732+
def idnits2_rfc_status(request):
1733+
filename = os.path.join(settings.DERIVED_DIR,'idnits2-rfc-status')
1734+
try:
1735+
with open(filename,'rb') as f:
1736+
blob = f.read()
1737+
return HttpResponse(blob,content_type='text/plain;charset=utf-8')
1738+
except Exception as e:
1739+
log.log('Failed to read idnits2-rfc-status:'+str(e))
1740+
raise Http404
1741+
1742+
1743+
def idnits2_state(request, name, rev=None):
1744+
doc = get_object_or_404(Document, docalias__name=name)
1745+
if doc.type_id!='draft':
1746+
raise Http404
1747+
zero_revision = NewRevisionDocEvent.objects.filter(doc=doc,rev='00').first()
1748+
if zero_revision:
1749+
doc.created = zero_revision.time
1750+
else:
1751+
doc.created = doc.docevent_set.order_by('-time').first().time
1752+
if doc.std_level:
1753+
doc.deststatus = doc.std_level.name
1754+
elif doc.intended_std_level:
1755+
doc.deststatus = doc.intended_std_level.name
1756+
else:
1757+
text = doc.text()
1758+
if text:
1759+
parsed_draft = Draft(text=doc.text(), source=name, name_from_source=False)
1760+
doc.deststatus = parsed_draft.get_status()
1761+
else:
1762+
doc.deststatus="Unknown"
1763+
return render(request, 'doc/idnits2-state.txt', context={'doc':doc}, content_type='text/plain;charset=utf-8')
1764+
1765+
1766+
1767+
1768+
1769+

ietf/settings.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,7 @@ def skip_unreadable_post(record):
682682
# write anything to this directory -- its content is maintained by ghostlinkd:
683683
INTERNET_ALL_DRAFTS_ARCHIVE_DIR = '/a/ietfdata/doc/draft/archive'
684684
MEETING_RECORDINGS_DIR = '/a/www/audio'
685+
DERIVED_DIR = '/a/ietfdata/derived'
685686

686687
DOCUMENT_FORMAT_WHITELIST = ["txt", "ps", "pdf", "xml", "html", ]
687688

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
{% load ietf_filters %}{% filter linebreaks_lf %}{% for k,l in obsitems %}{{k}} {{l|join:" "}}
2+
{% endfor %}{% endfilter %}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{% load ietf_filters %}{% filter linebreaks_lf %}{% comment %}
2+
{% endcomment %}Doc-created: {{doc.created|date:"Y-m-d"}};datatracker
3+
Doc-deststatus: {{doc.deststatus}};datatracker
4+
Doc-rev: {{doc.rev}};datatracker{% if doc.rfcnum %}
5+
Doc-rfcnum: {{doc.rfcnum}};datatracker{%endif%}
6+
{% endfilter %}

0 commit comments

Comments
 (0)