From 6b9aede79e25665c199064c362fc6524f8292882 Mon Sep 17 00:00:00 2001 From: Kesara Rathnayake Date: Thu, 19 Jan 2023 10:14:19 +1300 Subject: [PATCH] feat: Add editorial stream (#958) Add editorial stream as per #896 and Section 6.3 of RFC 9280. --- test.py | 54 +++++++++++++++++++++++++++++++++ tests/valid/docfile.html | 14 +++++---- tests/valid/manpage.txt | 17 +++++++---- xml2rfc/boilerplate_rfc_7841.py | 23 ++++++++++++++ xml2rfc/data/reference.rnc | 6 ++-- xml2rfc/data/reference.rng | 2 ++ xml2rfc/data/referencegroup.rng | 2 ++ xml2rfc/data/v3.rnc | 8 +++-- xml2rfc/data/v3.rng | 3 ++ xml2rfc/strings.py | 1 + xml2rfc/writers/preptool.py | 18 +++++------ 11 files changed, 122 insertions(+), 26 deletions(-) diff --git a/test.py b/test.py index 40a62a0e0..c719048b8 100644 --- a/test.py +++ b/test.py @@ -8,6 +8,7 @@ import xml2rfc import xml2rfc.utils +from xml2rfc.boilerplate_rfc_7841 import boilerplate_rfc_status_of_memo from xml2rfc.walkpdf import xmldoc from xml2rfc.writers.base import default_options @@ -582,5 +583,58 @@ def test_set_font_family(self): self.assertEqual(result, expected_svg) +class PrepToolWriterTest(unittest.TestCase): + '''PrepToolWriter tests''' + + def setUp(self): + xml2rfc.log.quiet = True + path = 'tests/input/elements.xml' + self.parser = xml2rfc.XmlRfcParser(path, + quiet=True, + options=default_options, + **options_for_xmlrfcparser) + self.xmlrfc = self.parser.parse() + self.writer = xml2rfc.PrepToolWriter(self.xmlrfc, quiet=True) + + def test_rfc_check_attribute_values_editorial(self): + rfc = lxml.etree.fromstring(''' + +''') + self.writer.root = rfc + + self.writer.check_attribute_values(rfc, None) + self.assertEqual(len(self.writer.errors), 0) + + def test_boilerplate_insert_status_of_memo_editorial(self): + rfc = lxml.etree.fromstring(''' + +''') + self.writer.options.rfc = True + self.writer.root = rfc + self.writer.rfcnumber = 9280 + + self.writer.boilerplate_insert_status_of_memo(rfc, rfc) + self.assertEqual(len(self.writer.errors), 0) + self.assertEqual(len(rfc.xpath('./section/name[text()="Status of This Memo"]')), 1) + paras = rfc.xpath('./section/t') + boilerplate_text = boilerplate_rfc_status_of_memo['editorial']['info']['n/a'] + self.assertEqual(len(paras), len(boilerplate_text)) + index = 0 + for boilerplate in boilerplate_text[-1]: + for line in boilerplate.split('\n')[1:-1]: + self.assertIn(line.strip(), paras[index].text) + index += 1 + + # test eref element + target = 'https://www.rfc-editor.org/info/rfc9280' + self.assertEqual(target, rfc.xpath('./section/t/eref')[0].get('target')) + + if __name__ == '__main__': unittest.main() diff --git a/tests/valid/docfile.html b/tests/valid/docfile.html index 2c25392c0..a9f869e68 100644 --- a/tests/valid/docfile.html +++ b/tests/valid/docfile.html @@ -2540,7 +2540,7 @@

Possible values:
-
( "IETF" | "IAB" | "IRTF" | "independent" ) +
( "IETF" | "IAB" | "IRTF" | "independent" | "editorial" )
Default value:
@@ -2778,7 +2778,7 @@

Possible values:
-
( "IETF" | "IAB" | "IRTF" | "independent" ) +
( "IETF" | "IAB" | "IRTF" | "independent" | "editorial" )
@@ -2925,7 +2925,7 @@

This element can be a child element of <reference>.

Content schema:
-
( "IETF" | "IAB" | "IRTF" | "independent" )? +
( "IETF" | "IAB" | "IRTF" | "independent" | "editorial" )?
@@ -4340,7 +4340,7 @@

attribute iprExtract { xsd:IDREF }?, [ a:defaultValue = "IETF" ] attribute submissionType { - "IETF" | "IAB" | "IRTF" | "independent" + "IETF" | "IAB" | "IRTF" | "independent" | "editorial" }?, attribute docName { text }?, [ a:defaultValue = "false" ] @@ -5386,7 +5386,7 @@

stream = element stream { - ( "IETF" | "IAB" | "IRTF" | "independent" )? + ( "IETF" | "IAB" | "IRTF" | "independent" | "editorial" )? } referencegroup = @@ -5408,7 +5408,9 @@

attribute asciiName { text }?, attribute asciiValue { text }?, attribute status { text }?, - attribute stream { "IETF" | "IAB" | "IRTF" | "independent" }?, + attribute stream { + "IETF" | "IAB" | "IRTF" | "independent" | "editorial" + }?, empty } diff --git a/tests/valid/manpage.txt b/tests/valid/manpage.txt index 7acbe22e5..09a3ac7dd 100644 --- a/tests/valid/manpage.txt +++ b/tests/valid/manpage.txt @@ -1505,7 +1505,8 @@ Table of Contents 2.49.12. "submissionType" Attribute - Possible values: ( "IETF" | "IAB" | "IRTF" | "independent" ) + Possible values: ( "IETF" | "IAB" | "IRTF" | "independent" | + "editorial" ) Default value: "IETF" The document stream, as described in [RFC7841]. (The RFC Series @@ -1648,7 +1649,8 @@ Table of Contents 2.51.5. "stream" Attribute - Possible values: ( "IETF" | "IAB" | "IRTF" | "independent" ) + Possible values: ( "IETF" | "IAB" | "IRTF" | "independent" | + "editorial" ) Deprecated. Use the element instead. @@ -1765,7 +1767,8 @@ Table of Contents This element can be a child element of . - Content schema: ( "IETF" | "IAB" | "IRTF" | "independent" )? + Content schema: ( "IETF" | "IAB" | "IRTF" | "independent" | + "editorial" )? 2.55. @@ -2753,7 +2756,7 @@ Appendix A. RELAX NG Schema attribute iprExtract { xsd:IDREF }?, [ a:defaultValue = "IETF" ] attribute submissionType { - "IETF" | "IAB" | "IRTF" | "independent" + "IETF" | "IAB" | "IRTF" | "independent" | "editorial" }?, attribute docName { text }?, [ a:defaultValue = "false" ] @@ -3799,7 +3802,7 @@ Appendix A. RELAX NG Schema stream = element stream { - ( "IETF" | "IAB" | "IRTF" | "independent" )? + ( "IETF" | "IAB" | "IRTF" | "independent" | "editorial" )? } referencegroup = @@ -3821,7 +3824,9 @@ Appendix A. RELAX NG Schema attribute asciiName { text }?, attribute asciiValue { text }?, attribute status { text }?, - attribute stream { "IETF" | "IAB" | "IRTF" | "independent" }?, + attribute stream { + "IETF" | "IAB" | "IRTF" | "independent" | "editorial" + }?, empty } diff --git a/xml2rfc/boilerplate_rfc_7841.py b/xml2rfc/boilerplate_rfc_7841.py index 932009057..cbb1880aa 100644 --- a/xml2rfc/boilerplate_rfc_7841.py +++ b/xml2rfc/boilerplate_rfc_7841.py @@ -549,4 +549,27 @@ ], }, }, + 'editorial': { + 'info': { + 'n/a' : [ """ + This document is not an Internet Standards Track specification; it is + published for informational purposes. + """, + + """ + This document is a product of the RFC Series Policy Definition + Process. It represents the consensus of the RFC Series Working + Group approved by the RFC Series Approval Board. Such documents + are not candidates for any level of Internet Standard; see + Section 2 of RFC 7841. + """, + + """ + Information about the current status of this document, any errata, + and how to provide feedback on it may be obtained at + . + """, + ], + }, + }, } diff --git a/xml2rfc/data/reference.rnc b/xml2rfc/data/reference.rnc index 1c42a6a65..fc6cb68ea 100644 --- a/xml2rfc/data/reference.rnc +++ b/xml2rfc/data/reference.rnc @@ -885,7 +885,7 @@ stream = element stream { - ( "IETF" | "IAB" | "IRTF" | "independent" )? + ( "IETF" | "IAB" | "IRTF" | "independent" | "editorial" )? } @@ -898,7 +898,9 @@ attribute asciiName { text }?, attribute asciiValue { text }?, attribute status { text }?, - attribute stream { "IETF" | "IAB" | "IRTF" | "independent" }?, + attribute stream { + "IETF" | "IAB" | "IRTF" | "independent" | "editorial" + }?, empty } diff --git a/xml2rfc/data/reference.rng b/xml2rfc/data/reference.rng index a1f07594e..956aaa0bf 100644 --- a/xml2rfc/data/reference.rng +++ b/xml2rfc/data/reference.rng @@ -2026,6 +2026,7 @@ IAB IRTF independent + editorial @@ -2056,6 +2057,7 @@ IAB IRTF independent + editorial diff --git a/xml2rfc/data/referencegroup.rng b/xml2rfc/data/referencegroup.rng index 34174541e..5ebd8c9d9 100644 --- a/xml2rfc/data/referencegroup.rng +++ b/xml2rfc/data/referencegroup.rng @@ -2048,6 +2048,7 @@ IAB IRTF independent + editorial @@ -2078,6 +2079,7 @@ IAB IRTF independent + editorial diff --git a/xml2rfc/data/v3.rnc b/xml2rfc/data/v3.rnc index 84fa1b117..2a1fa75b7 100644 --- a/xml2rfc/data/v3.rnc +++ b/xml2rfc/data/v3.rnc @@ -20,7 +20,7 @@ attribute iprExtract { xsd:IDREF }?, [ a:defaultValue = "IETF" ] attribute submissionType { - "IETF" | "IAB" | "IRTF" | "independent" + "IETF" | "IAB" | "IRTF" | "independent" | "editorial" }?, attribute docName { text }?, [ a:defaultValue = "false" ] @@ -1066,7 +1066,7 @@ stream = element stream { - ( "IETF" | "IAB" | "IRTF" | "independent" )? + ( "IETF" | "IAB" | "IRTF" | "independent" | "editorial" )? } referencegroup = @@ -1088,7 +1088,9 @@ attribute asciiName { text }?, attribute asciiValue { text }?, attribute status { text }?, - attribute stream { "IETF" | "IAB" | "IRTF" | "independent" }?, + attribute stream { + "IETF" | "IAB" | "IRTF" | "independent" | "editorial" + }?, empty } diff --git a/xml2rfc/data/v3.rng b/xml2rfc/data/v3.rng index 393a91696..d7281ea53 100644 --- a/xml2rfc/data/v3.rng +++ b/xml2rfc/data/v3.rng @@ -60,6 +60,7 @@ IAB IRTF independent + editorial @@ -2383,6 +2384,7 @@ IAB IRTF independent + editorial @@ -2435,6 +2437,7 @@ IAB IRTF independent + editorial diff --git a/xml2rfc/strings.py b/xml2rfc/strings.py index 9451cda62..0a5857443 100644 --- a/xml2rfc/strings.py +++ b/xml2rfc/strings.py @@ -22,4 +22,5 @@ 'IAB': 'Internet Architecture Board (IAB)', 'IRTF': 'Internet Research Task Force (IRTF)', 'independent': 'Independent Submission', + 'editorial': 'Editorial Stream', } diff --git a/xml2rfc/writers/preptool.py b/xml2rfc/writers/preptool.py index 4017eae2a..2d7a74dd7 100644 --- a/xml2rfc/writers/preptool.py +++ b/xml2rfc/writers/preptool.py @@ -257,7 +257,7 @@ def prep(self): './front;insert_boilerplate()', # 5.4.2. Insertion './front;insert_toc()', '.;check_series_and_submission_type()', # 5.4.2.1. Compare "submissionType" and "stream" - './/boilerplate;insert_status_of_memo()', # 5.4.2.2. "Status of this Memo" Insertion + './/boilerplate;insert_status_of_memo()', # 5.4.2.2. "Status of This Memo" Insertion './/boilerplate;insert_copyright_notice()', # 5.4.2.3. "Copyright Notice" Insertion './/boilerplate//section', # 5.2.7. Section "toc" attribute './/reference;insert_target()', # 5.4.3. "target" Insertion @@ -476,9 +476,9 @@ def check_attribute_values(self, e, p): if consensus: self.err(self.root, "Expected no consensus setting for IRTF stream and no workgroup, but found '%s'. Ignoring it." % consensus) consensus = 'n/a' - elif stream == 'independent': + elif stream == 'independent' or stream == 'editorial': if consensus: - self.err(self.root, "Expected no consensus setting for independent stream, but found '%s'. Ignoring it." % consensus) + self.err(self.root, "Expected no consensus setting for %s stream, but found '%s'. Ignoring it." % (stream, consensus)) consensus = 'n/a' elif consensus != None: pass @@ -1023,9 +1023,9 @@ def check_series_and_submission_type(self, e, p): for i in series_info_list: i.set('stream', stream) - # 5.4.2.2. "Status of this Memo" Insertion + # 5.4.2.2. "Status of This Memo" Insertion # - # Add the "Status of this Memo" section to the element + # Add the "Status of This Memo" section to the element # with current values. The application will use the "submissionType", # and "consensus" attributes of the element, the # element, and the "status" and "stream" attributes of the @@ -1036,10 +1036,10 @@ def boilerplate_insert_status_of_memo(self, e, p): return if self.root.get('ipr') == 'none': return - # submissionType: "IETF" | "IAB" | "IRTF" | "independent" + # submissionType: "IETF" | "IAB" | "IRTF" | "independent" | "editorial" # consensus: "false" | "true" # category: "std" | "bcp" | "exp" | "info" | "historic" - b = e.xpath('./section/name[text()="Status of this Memo"]') + b = e.xpath('./section/name[text()="Status of This Memo"]') existing_status_of_memo = b[0] if b else None if existing_status_of_memo: if self.liberal: @@ -1070,7 +1070,7 @@ def boilerplate_insert_status_of_memo(self, e, p): # if stream == 'IRTF' and workgroup == None: consensus = 'n/a' - elif stream == 'independent': + elif stream == 'independent' or stream == 'editorial': consensus = 'n/a' try: for para in boilerplate_rfc_status_of_memo[stream][category][consensus]: @@ -1080,7 +1080,7 @@ def boilerplate_insert_status_of_memo(self, e, p): except KeyError as exception: if str(exception) in ["'rfc_number'", "'group_name'"]: # Error in string expansion - self.die(p, 'Expected to have a value for %s when expanding the "Status of this Memo" boilerplate, but found none.' % str(exception)) + self.die(p, 'Expected to have a value for %s when expanding the "Status of This Memo" boilerplate, but found none.' % str(exception)) else: # Error in boilerplate dictionary indexes self.die(self.root, 'Unexpected attribute combination(%s): ' % (exception, stream, category, consensus))