Skip to content

Commit 7c7219f

Browse files
authored
feat: Generate std-index.txt (ietf-tools#10665)
* feat: Generate std-index.txt * style: Ruff ruff Good boy! * test: Fix flaky test * test: Add tests for std-index.txt
1 parent a46a2ef commit 7c7219f

3 files changed

Lines changed: 193 additions & 2 deletions

File tree

ietf/sync/rfcindex.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,71 @@ def get_bcp_text_index_entries():
350350
return entries
351351

352352

353+
def get_std_text_index_entries():
354+
"""Returns STD entries for std-index.txt"""
355+
entries = []
356+
357+
highest_std_number = (
358+
Document.objects.filter(type_id="std")
359+
.annotate(
360+
number=Cast(
361+
Substr("name", 4, None),
362+
output_field=models.IntegerField(),
363+
)
364+
)
365+
.order_by("-number")
366+
.first()
367+
.number
368+
)
369+
370+
for std_number in range(1, highest_std_number + 1):
371+
std_name = f"STD{std_number}"
372+
std = Document.objects.filter(type_id="std", name=f"{std_name.lower()}").first()
373+
374+
if std and std.contains():
375+
entry = subseries_text_line(
376+
(
377+
f"[{std_name}]"
378+
f"{' ' * (SS_TXT_CUE_COL_WIDTH - len(std_name) - 2 - SS_TXT_MARGIN)}"
379+
f"Internet Standard {std_number},"
380+
),
381+
first=True,
382+
)
383+
entry += "\n"
384+
entry += subseries_text_line(
385+
f"<{settings.RFC_EDITOR_INFO_BASE_URL}{std_name.lower()}>."
386+
)
387+
entry += "\n"
388+
entry += subseries_text_line(
389+
"At the time of writing, this STD comprises the following:"
390+
)
391+
entry += "\n\n"
392+
rfcs = sorted(std.contains(), key=lambda x: x.rfc_number)
393+
for rfc in rfcs:
394+
authors = ", ".join(
395+
author.format_for_titlepage() for author in rfc.rfcauthor_set.all()
396+
)
397+
entry += subseries_text_line(
398+
(
399+
f'{authors}, "{rfc.title}", STD¶{std_number}, RFC¶{rfc.rfc_number}, '
400+
f"DOI¶{rfc.doi}, {rfc.pub_date().strftime('%B %Y')}, "
401+
f"<{settings.RFC_EDITOR_INFO_BASE_URL}rfc{rfc.rfc_number}>."
402+
)
403+
).replace("¶", " ")
404+
entry += "\n\n"
405+
else:
406+
entry = subseries_text_line(
407+
(
408+
f"[{std_name}]"
409+
f"{' ' * (SS_TXT_CUE_COL_WIDTH - len(std_name) - 2 - SS_TXT_MARGIN)}"
410+
f"Internet Standard {std_number} currently contains no RFCs"
411+
),
412+
first=True,
413+
)
414+
entries.append(entry)
415+
return entries
416+
417+
353418
def add_subseries_xml_index_entries(rfc_index, ss_type, include_all=False):
354419
"""Add subseries entries for rfc-index.xml"""
355420
# subseries docs annotated with numeric number
@@ -579,3 +644,18 @@ def create_bcp_txt_index():
579644
},
580645
)
581646
save_to_red_bucket("bcp-index.txt", index)
647+
648+
649+
def create_std_txt_index():
650+
"""Create text index of STDs"""
651+
DATE_FMT = "%m/%d/%Y"
652+
created_on = timezone.now().strftime(DATE_FMT)
653+
log("Creating std-index.txt")
654+
index = render_to_string(
655+
"sync/std-index.txt",
656+
{
657+
"created_on": created_on,
658+
"stds": get_std_text_index_entries(),
659+
},
660+
)
661+
save_to_red_bucket("std-index.txt", index)

ietf/sync/tests_rfcindex.py

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
from ietf.doc.factories import (
1111
BcpFactory,
12+
StdFactory,
1213
IndividualRfcFactory,
1314
PublishedRfcDocEventFactory,
1415
)
@@ -17,6 +18,7 @@
1718
create_bcp_txt_index,
1819
create_rfc_txt_index,
1920
create_rfc_xml_index,
21+
create_std_txt_index,
2022
format_rfc_number,
2123
get_april1_rfc_numbers,
2224
get_publication_std_levels,
@@ -78,6 +80,9 @@ def setUp(self):
7880
# Create a BCP with non-April Fools RFC
7981
self.bcp = BcpFactory(contains=[self.rfc], name="bcp11")
8082

83+
# Create a STD with non-April Fools RFC
84+
self.std = StdFactory(contains=[self.rfc], name="std11")
85+
8186
# Set up a publication-std-levels.json file to indicate the publication
8287
# standard of self.rfc as different from its current value
8388
red_bucket.save(
@@ -146,7 +151,7 @@ def test_create_rfc_xml_index(self, mock_save):
146151

147152
children = list(index) # elements as list
148153
# Should be one rfc-not-issued-entry
149-
self.assertEqual(len(children), 14)
154+
self.assertEqual(len(children), 15)
150155
self.assertEqual(
151156
[
152157
c.find(f"{ns}doc-id").text
@@ -236,7 +241,62 @@ def test_create_bcp_txt_index(self, mock_save):
236241
contents,
237242
)
238243
self.assertIn(
239-
f'BCP 11, RFC {self.rfc.rfc_number},',
244+
"BCP 11,",
245+
contents,
246+
)
247+
self.assertIn(
248+
f"RFC {self.rfc.rfc_number},",
249+
contents,
250+
)
251+
252+
@override_settings(RFCINDEX_INPUT_PATH="input/")
253+
@mock.patch("ietf.sync.rfcindex.save_to_red_bucket")
254+
def test_create_std_txt_index(self, mock_save):
255+
create_std_txt_index()
256+
self.assertEqual(mock_save.call_count, 1)
257+
self.assertEqual(mock_save.call_args[0][0], "std-index.txt")
258+
contents = mock_save.call_args[0][1]
259+
self.assertTrue(isinstance(contents, str))
260+
# starts from 1
261+
self.assertIn(
262+
"[STD1]",
263+
contents,
264+
)
265+
# fill up to 11
266+
self.assertIn(
267+
"[STD10]",
268+
contents,
269+
)
270+
# but not to 12
271+
self.assertNotIn(
272+
"[STD12]",
273+
contents,
274+
)
275+
# Test empty STDs
276+
self.assertIn(
277+
"Internet Standard 9 currently contains no RFCs",
278+
contents,
279+
)
280+
# No zero prefix!
281+
self.assertNotIn(
282+
"[STD0001]",
283+
contents,
284+
)
285+
# Has STD11 with a RFC
286+
self.assertIn(
287+
"Internet Standard 11,",
288+
contents,
289+
)
290+
self.assertIn(
291+
f'"{self.rfc.title}"',
292+
contents,
293+
)
294+
self.assertIn(
295+
"STD 11,",
296+
contents,
297+
)
298+
self.assertIn(
299+
f"RFC {self.rfc.rfc_number},",
240300
contents,
241301
)
242302

ietf/templates/sync/std-index.txt

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
2+
3+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4+
5+
STD INDEX
6+
-------------
7+
8+
(CREATED ON: {{created_on}}.)
9+
10+
This file contains citations for all STDs in numeric order. Each
11+
STD represents a single Internet Standard technical specification,
12+
composed of one or more RFCs with Internet Standard status.
13+
14+
STD citations appear in this format:
15+
16+
[STD#] Best Current Practice #,
17+
<STD URL>.
18+
At the time of writing, this STD comprises the following:
19+
20+
Author 1, Author 2, "Title of the RFC", STD #, RFC №,
21+
DOI DOI string, Issue date,
22+
<RFC URL>.
23+
24+
For example:
25+
26+
[STD6] Internet Standard 6,
27+
<https://www.rfc-editor.org/info/std6>.
28+
At the time of writing, this STD comprises the following:
29+
30+
J. Postel, "User Datagram Protocol", STD 6, RFC 768,
31+
DOI 10.17487/RFC0768, August 1980,
32+
<https://www.rfc-editor.org/info/rfc768>.
33+
34+
Key to fields:
35+
36+
# is the STD number.
37+
38+
№ is the RFC number.
39+
40+
STDs and other RFCs may be obtained from https://www.rfc-editor.org.
41+
42+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
43+
44+
STD INDEX
45+
---------
46+
47+
48+
49+
{% for std in stds %}{{std|safe}}
50+
51+
{% endfor %}

0 commit comments

Comments
 (0)