Infra: replace feedgen/lxml dependency to test Python 3.12-dev (#2973)

This commit is contained in:
Hugo van Kemenade 2023-01-21 16:08:38 +02:00 committed by GitHub
parent a48b585960
commit b173099ac6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 46 additions and 45 deletions

View File

@ -9,7 +9,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
python-version: ["3.x", "3.11-dev"] python-version: ["3.x", "3.12-dev"]
steps: steps:
- name: 🛎️ Checkout - name: 🛎️ Checkout

View File

@ -22,11 +22,8 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
python-version: ["3.9", "3.10", "3.11-dev"] python-version: ["3.9", "3.10", "3.11", "3.12-dev"]
os: [windows-latest, macos-latest, ubuntu-latest] os: [windows-latest, macos-latest, ubuntu-latest]
# lxml doesn't yet install for 3.11 on Windows
exclude:
- { python-version: "3.11-dev", os: windows-latest }
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3

View File

@ -29,7 +29,7 @@ check-links: venv
## rss to generate the peps.rss file ## rss to generate the peps.rss file
.PHONY: rss .PHONY: rss
rss: venv rss: venv
$(VENVDIR)/bin/python3 generate_rss.py $(VENVDIR)/bin/python3 generate_rss.py -o $(OUTPUT_DIR)
## clean to remove the venv and build files ## clean to remove the venv and build files
.PHONY: clean .PHONY: clean

View File

@ -2,8 +2,10 @@
# This file is placed in the public domain or under the # This file is placed in the public domain or under the
# CC0-1.0-Universal license, whichever is more permissive. # CC0-1.0-Universal license, whichever is more permissive.
import argparse
import datetime import datetime
import email.utils import email.utils
from html import escape
from pathlib import Path from pathlib import Path
import re import re
@ -12,19 +14,16 @@ from docutils import nodes
from docutils import utils from docutils import utils
from docutils.parsers import rst from docutils.parsers import rst
from docutils.parsers.rst import roles from docutils.parsers.rst import roles
from feedgen import entry
from feedgen import feed
# get the directory with the PEP sources # get the directory with the PEP sources
PEP_ROOT = Path(__file__).parent PEP_ROOT = Path(__file__).parent
# Monkeypatch feedgen.util.formatRFC2822
def _format_rfc_2822(dt: datetime.datetime) -> str: def _format_rfc_2822(dt: datetime.datetime) -> str:
dt = dt.replace(tzinfo=datetime.timezone.utc)
return email.utils.format_datetime(dt, usegmt=True) return email.utils.format_datetime(dt, usegmt=True)
entry.formatRFC2822 = feed.formatRFC2822 = _format_rfc_2822
line_cache: dict[Path, dict[str, str]] = {} line_cache: dict[Path, dict[str, str]] = {}
# Monkeypatch PEP and RFC reference roles to match Sphinx behaviour # Monkeypatch PEP and RFC reference roles to match Sphinx behaviour
@ -137,6 +136,15 @@ def pep_abstract(full_path: Path) -> str:
def main(): def main():
parser = argparse.ArgumentParser(description="Generate RSS feed")
parser.add_argument(
"-o",
"--output-dir",
default="build", # synchronise with render.yaml -> deploy step
help="Output directory, relative to root. Default 'build'.",
)
args = parser.parse_args()
# get list of peps with creation time (from "Created:" string in pep source) # 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-????.???")) peps_with_dt = sorted((pep_creation(path), path) for path in PEP_ROOT.glob("pep-????.???"))
@ -152,21 +160,20 @@ def main():
author = first_line_starting_with(full_path, "Author:") author = first_line_starting_with(full_path, "Author:")
if "@" in author or " at " in author: if "@" in author or " at " in author:
parsed_authors = email.utils.getaddresses([author]) parsed_authors = email.utils.getaddresses([author])
# ideal would be to pass as a list of dicts with names and emails to
# item.author, but FeedGen's RSS <author/> output doesn't pass W3C
# validation (as of 12/06/2021)
joined_authors = ", ".join(f"{name} ({email_address})" for name, email_address in parsed_authors) joined_authors = ", ".join(f"{name} ({email_address})" for name, email_address in parsed_authors)
else: else:
joined_authors = author joined_authors = author
url = f"https://peps.python.org/pep-{pep_num:0>4}/" url = f"https://peps.python.org/pep-{pep_num:0>4}/"
item = entry.FeedEntry() item = f"""\
item.title(f"PEP {pep_num}: {title}") <item>
item.link(href=url) <title>PEP {pep_num}: {escape(title, quote=False)}</title>
item.description(pep_abstract(full_path)) <link>{escape(url, quote=False)}</link>
item.guid(url, permalink=True) <description>{escape(pep_abstract(full_path), quote=False)}</description>
item.published(dt.replace(tzinfo=datetime.timezone.utc)) # ensure datetime has a timezone <author>{escape(joined_authors, quote=False)}</author>
item.author(email=joined_authors) <guid isPermaLink="true">{url}</guid>
<pubDate>{_format_rfc_2822(dt)}</pubDate>
</item>"""
items.append(item) items.append(item)
# The rss envelope # The rss envelope
@ -175,28 +182,28 @@ def main():
language features, and some meta-information like release language features, and some meta-information like release
procedure and schedules. procedure and schedules.
""" """
last_build_date = _format_rfc_2822(datetime.datetime.utcnow())
# Setup feed generator items = "\n".join(reversed(items))
fg = feed.FeedGenerator() output = f"""\
fg.language("en") <?xml version='1.0' encoding='UTF-8'?>
fg.generator("") <rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0">
fg.docs("https://cyber.harvard.edu/rss/rss.html") <channel>
<title>Newest Python PEPs</title>
# Add metadata <link>https://peps.python.org/peps.rss</link>
fg.title("Newest Python PEPs") <description>{" ".join(desc.split())}</description>
fg.link(href="https://peps.python.org") <atom:link href="https://peps.python.org/peps.rss" rel="self"/>
fg.link(href="https://peps.python.org/peps.rss", rel="self") <docs>https://cyber.harvard.edu/rss/rss.html</docs>
fg.description(" ".join(desc.split())) <language>en</language>
fg.lastBuildDate(datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc)) <lastBuildDate>{last_build_date}</lastBuildDate>
{items}
# Add PEP information (ordered by newest first) </channel>
for item in items: </rss>
fg.add_entry(item) """
# output directory for target HTML files # output directory for target HTML files
out_dir = PEP_ROOT / "build" out_dir = PEP_ROOT / args.output_dir
out_dir.mkdir(exist_ok=True) out_dir.mkdir(exist_ok=True, parents=True)
out_dir.joinpath("peps.rss").write_bytes(fg.rss_str(pretty=True)) out_dir.joinpath("peps.rss").write_text(output)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -3,7 +3,7 @@ version: 2
build: build:
os: ubuntu-22.04 os: ubuntu-22.04
tools: tools:
python: "3.10" python: "3.11"
commands: commands:
- make dirhtml JOBS=$(nproc) OUTPUT_DIR=_readthedocs/html - make dirhtml JOBS=$(nproc) OUTPUT_DIR=_readthedocs/html

View File

@ -5,9 +5,6 @@ Pygments >= 2.9.0
Sphinx >= 5.1.1, != 6.1.0, != 6.1.1 Sphinx >= 5.1.1, != 6.1.0, != 6.1.1
docutils >= 0.19.0 docutils >= 0.19.0
# For RSS
feedgen >= 0.9.0 # For RSS feed
# For tests # For tests
pytest pytest
pytest-cov pytest-cov

View File

@ -1,6 +1,6 @@
[tox] [tox]
envlist = envlist =
py{311, 310, 39} py{312, 311, 310, 39}
skipsdist = true skipsdist = true
[testenv] [testenv]