← 返回首页
feat: Generate std-index.txt (#10665) · ietf-tools/datatracker@7c7219f · GitHub
Skip to content

Navigation Menu

Toggle navigation
Sign in
Appearance settings
Search or jump to...

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Include my email address so I can be contacted

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Resetting focus

Commit 7c7219f

Browse files
authored
feat: Generate std-index.txt (#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)

Footer

© 2026 GitHub, Inc.