From ee0c86603f5136b80a27edf7bf2d12819e6abbb8 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Thu, 10 Mar 2022 11:27:25 +0200 Subject: [PATCH 1/4] Infra: build peps.rss from input txt and rst files --- generate_rss.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/generate_rss.py b/generate_rss.py index 2322fbd43ca..a16b83cb1ac 100755 --- a/generate_rss.py +++ b/generate_rss.py @@ -79,10 +79,17 @@ def pep_abstract(full_path: Path) -> str: def main(): # get the directory with the PEP sources + in_dir = Path(__file__).parent + + # get the output directory for target HTML files out_dir = Path(__file__).parent / "build" - # get list of peps with creation time (from "Created:" string in pep source) - peps_with_dt = sorted((pep_creation(path), path) for path in out_dir.glob("pep-????.*")) + # get list of source peps + peps = list(in_dir.glob('pep-*.txt')) + peps.extend(in_dir.glob('pep-*.rst')) + + # sort peps by creation time (from "Created:" string in pep source) + peps_with_dt = sorted((pep_creation(path), path) for path in peps) # generate rss items for 10 most recent peps items = [] From aef827728f346af792cd93975c7be426f7fe54f4 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Fri, 11 Mar 2022 20:33:21 +0000 Subject: [PATCH 2/4] Handle new reference styles --- generate_rss.py | 78 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 66 insertions(+), 12 deletions(-) diff --git a/generate_rss.py b/generate_rss.py index a16b83cb1ac..360b5d7f417 100755 --- a/generate_rss.py +++ b/generate_rss.py @@ -5,15 +5,20 @@ import datetime import email.utils from pathlib import Path +import re import docutils from docutils import frontend from docutils import nodes from docutils import utils from docutils.parsers import rst +from docutils.parsers.rst import roles from feedgen import entry from feedgen import feed +# get the directory with the PEP sources +PEP_ROOT = Path(__file__).parent + # Monkeypatch feedgen.util.formatRFC2822 def _format_rfc_2822(dt: datetime.datetime) -> str: @@ -31,6 +36,63 @@ def findall(self, *args, **kwargs): entry.formatRFC2822 = feed.formatRFC2822 = _format_rfc_2822 line_cache: dict[Path, dict[str, str]] = {} +# Monkeypatch PEP and RFC reference roles to match Sphinx behaviour +EXPLICIT_TITLE_RE = re.compile(r'^(.+?)\s*(?$', re.DOTALL) +def _pep_reference_role(role, rawtext, text, lineno, inliner, + options={}, content=[]): + matched = EXPLICIT_TITLE_RE.match(text) + if matched: + title = utils.unescape(matched.group(1)) + target = utils.unescape(matched.group(2)) + else: + target = utils.unescape(text) + title = "PEP " + utils.unescape(text) + pep_str, _, fragment = target.partition("#") + try: + pepnum = int(pep_str) + if pepnum < 0 or pepnum > 9999: + raise ValueError + except ValueError: + msg = inliner.reporter.error( + f'PEP number must be a number from 0 to 9999; "{pep_str}" is invalid.', + line=lineno) + prb = inliner.problematic(rawtext, rawtext, msg) + return [prb], [msg] + # Base URL mainly used by inliner.pep_reference; so this is correct: + ref = (inliner.document.settings.pep_base_url + + inliner.document.settings.pep_file_url_template % pepnum) + if fragment: + ref += "#" + fragment + roles.set_classes(options) + return [nodes.reference(rawtext, title, refuri=ref, **options)], [] +def _rfc_reference_role(role, rawtext, text, lineno, inliner, + options={}, content=[]): + matched = EXPLICIT_TITLE_RE.match(text) + if matched: + title = utils.unescape(matched.group(1)) + target = utils.unescape(matched.group(2)) + else: + target = utils.unescape(text) + title = "RFC " + utils.unescape(text) + pep_str, _, fragment = target.partition("#") + try: + rfcnum = int(pep_str) + if rfcnum < 0 or rfcnum > 9999: + raise ValueError + except ValueError: + msg = inliner.reporter.error( + f'RFC number must be a number from 0 to 9999; "{pep_str}" is invalid.', + line=lineno) + prb = inliner.problematic(rawtext, rawtext, msg) + return [prb], [msg] + ref = (inliner.document.settings.rfc_base_url + inliner.rfc_url % rfcnum) + if fragment: + ref += "#" + fragment + roles.set_classes(options) + return [nodes.reference(rawtext, title, refuri=ref, **options)], [] +roles.register_canonical_role("pep-reference", _pep_reference_role) +roles.register_canonical_role("rfc-reference", _rfc_reference_role) + def first_line_starting_with(full_path: Path, text: str) -> str: # Try and retrieve from cache @@ -78,18 +140,8 @@ def pep_abstract(full_path: Path) -> str: def main(): - # get the directory with the PEP sources - in_dir = Path(__file__).parent - - # get the output directory for target HTML files - out_dir = Path(__file__).parent / "build" - - # get list of source peps - peps = list(in_dir.glob('pep-*.txt')) - peps.extend(in_dir.glob('pep-*.rst')) - - # sort peps by creation time (from "Created:" string in pep source) - peps_with_dt = sorted((pep_creation(path), path) for path in peps) + # get list of peps with creation time (from "Created:" string in pep source) + peps_with_dt = sorted((pep_creation(path), path) for path in PEP_ROOT.glob("pep-????.???")) # generate rss items for 10 most recent peps items = [] @@ -144,6 +196,8 @@ def main(): for item in items: fg.add_entry(item) + # output directory for target HTML files + out_dir = PEP_ROOT / "build" out_dir.mkdir(exist_ok=True) out_dir.joinpath("peps.rss").write_bytes(fg.rss_str(pretty=True)) From 6c6c22349d4f543a7cacb806b73692fcfb1d1ca3 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Fri, 11 Mar 2022 20:38:10 +0000 Subject: [PATCH 3/4] Fix last warnings --- generate_rss.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/generate_rss.py b/generate_rss.py index 360b5d7f417..cb0e4f8bba1 100755 --- a/generate_rss.py +++ b/generate_rss.py @@ -123,17 +123,17 @@ def pep_creation(full_path: Path) -> datetime.datetime: return datetime.datetime.strptime(created_str, "%d-%b-%Y") -def parse_rst(text: str) -> nodes.document: +def parse_rst(full_path: Path) -> nodes.document: + text = full_path.read_text(encoding="utf-8") settings = frontend.OptionParser((rst.Parser,)).get_default_values() - document = utils.new_document('', settings=settings) - rst.Parser().parse(text, document) + document = utils.new_document(f'<{full_path}>', settings=settings) + rst.Parser(rfc2822=True).parse(text, document) return document def pep_abstract(full_path: Path) -> str: """Return the first paragraph of the PEP abstract""" - text = full_path.read_text(encoding="utf-8") - for node in parse_rst(text).findall(nodes.section): + for node in parse_rst(full_path).findall(nodes.section): if node.next_node(nodes.title).astext() == "Abstract": return node.next_node(nodes.paragraph).astext().strip().replace("\n", " ") return "" From 52ca977230bf00e886a2d14dfd08b2286d98bc0d Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Fri, 11 Mar 2022 21:46:54 +0000 Subject: [PATCH 4/4] Add vertical whitespace --- generate_rss.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/generate_rss.py b/generate_rss.py index cb0e4f8bba1..7af56c26375 100755 --- a/generate_rss.py +++ b/generate_rss.py @@ -38,6 +38,8 @@ def findall(self, *args, **kwargs): # Monkeypatch PEP and RFC reference roles to match Sphinx behaviour EXPLICIT_TITLE_RE = re.compile(r'^(.+?)\s*(?$', re.DOTALL) + + def _pep_reference_role(role, rawtext, text, lineno, inliner, options={}, content=[]): matched = EXPLICIT_TITLE_RE.match(text) @@ -65,6 +67,8 @@ def _pep_reference_role(role, rawtext, text, lineno, inliner, ref += "#" + fragment roles.set_classes(options) return [nodes.reference(rawtext, title, refuri=ref, **options)], [] + + def _rfc_reference_role(role, rawtext, text, lineno, inliner, options={}, content=[]): matched = EXPLICIT_TITLE_RE.match(text) @@ -90,6 +94,8 @@ def _rfc_reference_role(role, rawtext, text, lineno, inliner, ref += "#" + fragment roles.set_classes(options) return [nodes.reference(rawtext, title, refuri=ref, **options)], [] + + roles.register_canonical_role("pep-reference", _pep_reference_role) roles.register_canonical_role("rfc-reference", _rfc_reference_role)