Skip to content

Commit 2d4c98d

Browse files
authored
Infra: Prepare for moving PEPs to a subfolder (#3417)
1 parent e7314c9 commit 2d4c98d

File tree

12 files changed

+71
-56
lines changed

12 files changed

+71
-56
lines changed

.github/CODEOWNERS

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ requirements.txt @AA-Turner
1212
infra/ @ewdurbin
1313

1414
pep_sphinx_extensions/ @AA-Turner
15-
AUTHOR_OVERRIDES.csv @AA-Turner
1615
build.py @AA-Turner
1716
conf.py @AA-Turner
1817
contents.rst @AA-Turner

conf.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33

44
"""Configuration for building PEPs using Sphinx."""
55

6+
import os
67
from pathlib import Path
78
import sys
89

9-
sys.path.append(str(Path(".").absolute()))
10+
_ROOT = Path(__file__).resolve().parent
11+
sys.path.append(os.fspath(_ROOT))
1012

1113
# -- Project information -----------------------------------------------------
1214

@@ -60,16 +62,18 @@
6062

6163
# -- Options for HTML output -------------------------------------------------
6264

65+
_PSE_PATH = _ROOT / "pep_sphinx_extensions"
66+
6367
# HTML output settings
6468
html_math_renderer = "maths_to_html" # Maths rendering
6569

6670
# Theme settings
67-
html_theme_path = ["pep_sphinx_extensions"]
71+
html_theme_path = [os.fspath(_PSE_PATH)]
6872
html_theme = "pep_theme" # The actual theme directory (child of html_theme_path)
6973
html_use_index = False # Disable index (we use PEP 0)
7074
html_style = "" # must be defined here or in theme.conf, but is unused
7175
html_permalinks = False # handled in the PEPContents transform
7276
html_baseurl = "https://peps.python.org" # to create the CNAME file
7377
gettext_auto_build = False # speed-ups
7478

75-
templates_path = ["pep_sphinx_extensions/pep_theme/templates"] # Theme template relative paths from `confdir`
79+
templates_path = [os.fspath(_PSE_PATH / "pep_theme" / "templates")] # Theme template relative paths from `confdir`

pep_sphinx_extensions/pep_processor/parsing/pep_banner_directive.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from docutils import nodes
66
from docutils.parsers import rst
77

8-
98
PYPA_SPEC_BASE_URL = "https://packaging.python.org/en/latest/specifications/"
109

1110

pep_sphinx_extensions/pep_processor/transforms/pep_footer.py

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import datetime as dt
1+
import time
22
from pathlib import Path
33
import subprocess
44

@@ -23,7 +23,7 @@ class PEPFooter(transforms.Transform):
2323

2424
def apply(self) -> None:
2525
pep_source_path = Path(self.document["source"])
26-
if not pep_source_path.match("pep-*"):
26+
if not pep_source_path.match("pep-????.???"):
2727
return # not a PEP file, exit early
2828

2929
# Iterate through sections from the end of the document
@@ -62,42 +62,44 @@ def _add_source_link(pep_source_path: Path) -> nodes.paragraph:
6262
def _add_commit_history_info(pep_source_path: Path) -> nodes.paragraph:
6363
"""Use local git history to find last modified date."""
6464
try:
65-
since_epoch = LAST_MODIFIED_TIMES[pep_source_path.name]
65+
iso_time = _LAST_MODIFIED_TIMES[pep_source_path.stem]
6666
except KeyError:
6767
return nodes.paragraph()
6868

69-
epoch_dt = dt.datetime.fromtimestamp(since_epoch, dt.timezone.utc)
70-
iso_time = epoch_dt.isoformat(sep=" ")
7169
commit_link = f"https://github.com/python/peps/commits/main/{pep_source_path.name}"
7270
link_node = nodes.reference("", f"{iso_time} GMT", refuri=commit_link)
7371
return nodes.paragraph("", "Last modified: ", link_node)
7472

7573

7674
def _get_last_modified_timestamps():
7775
# get timestamps and changed files from all commits (without paging results)
78-
args = ["git", "--no-pager", "log", "--format=#%at", "--name-only"]
79-
with subprocess.Popen(args, stdout=subprocess.PIPE) as process:
80-
all_modified = process.stdout.read().decode("utf-8")
81-
process.stdout.close()
82-
if process.wait(): # non-zero return code
83-
return {}
76+
args = ("git", "--no-pager", "log", "--format=#%at", "--name-only")
77+
ret = subprocess.run(args, stdout=subprocess.PIPE, text=True, encoding="utf-8")
78+
if ret.returncode: # non-zero return code
79+
return {}
80+
all_modified = ret.stdout
8481

8582
# set up the dictionary with the *current* files
86-
last_modified = {path.name: 0 for path in Path().glob("pep-*") if path.suffix in {".txt", ".rst"}}
83+
peps_dir = Path(__file__, "..", "..", "..", "..").resolve()
84+
last_modified = {path.stem: "" for path in peps_dir.glob("pep-????.???") if path.suffix in {".txt", ".rst"}}
8785

8886
# iterate through newest to oldest, updating per file timestamps
8987
change_sets = all_modified.removeprefix("#").split("#")
9088
for change_set in change_sets:
9189
timestamp, files = change_set.split("\n", 1)
9290
for file in files.strip().split("\n"):
93-
if file.startswith("pep-") and file[-3:] in {"txt", "rst"}:
94-
if last_modified.get(file) == 0:
95-
try:
96-
last_modified[file] = float(timestamp)
97-
except ValueError:
98-
pass # if float conversion fails
91+
if not file.startswith("pep-") or not file.endswith((".rst", ".txt")):
92+
continue # not a PEP
93+
file = file[:-4]
94+
if last_modified.get(file) != "":
95+
continue # most recent modified date already found
96+
try:
97+
y, m, d, hh, mm, ss, *_ = time.gmtime(float(timestamp))
98+
except ValueError:
99+
continue # if float conversion fails
100+
last_modified[file] = f"{y:04}-{m:02}-{d:02} {hh:02}:{mm:02}:{ss:02}"
99101

100102
return last_modified
101103

102104

103-
LAST_MODIFIED_TIMES = _get_last_modified_timestamps()
105+
_LAST_MODIFIED_TIMES = _get_last_modified_timestamps()

pep_sphinx_extensions/pep_theme/templates/page.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ <h1>Python Enhancement Proposals</h1>
4343
<h2>Contents</h2>
4444
{{ toc }}
4545
<br>
46-
{%- if not (sourcename.startswith("pep-0000") or sourcename.startswith("topic")) %}
46+
{%- if not sourcename.startswith(("pep-0000", "topic")) %}
4747
<a id="source" href="https://github.com/python/peps/blob/main/{{sourcename}}">Page Source (GitHub)</a>
4848
{%- endif %}
4949
</nav>

pep_sphinx_extensions/pep_zero_generator/pep_index_generator.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,22 @@
1818
from __future__ import annotations
1919

2020
import json
21+
import os
2122
from pathlib import Path
2223
from typing import TYPE_CHECKING
2324

24-
from pep_sphinx_extensions.pep_zero_generator.constants import SUBINDICES_BY_TOPIC
2525
from pep_sphinx_extensions.pep_zero_generator import parser
2626
from pep_sphinx_extensions.pep_zero_generator import subindices
2727
from pep_sphinx_extensions.pep_zero_generator import writer
28+
from pep_sphinx_extensions.pep_zero_generator.constants import SUBINDICES_BY_TOPIC
2829

2930
if TYPE_CHECKING:
3031
from sphinx.application import Sphinx
3132
from sphinx.environment import BuildEnvironment
3233

3334

34-
def _parse_peps() -> list[parser.PEP]:
35+
def _parse_peps(path: Path) -> list[parser.PEP]:
3536
# Read from root directory
36-
path = Path(".")
3737
peps: list[parser.PEP] = []
3838

3939
for file_path in path.iterdir():
@@ -52,16 +52,21 @@ def create_pep_json(peps: list[parser.PEP]) -> str:
5252
return json.dumps({pep.number: pep.full_details for pep in peps}, indent=1)
5353

5454

55+
def write_peps_json(peps: list[parser.PEP], path: Path) -> None:
56+
# Create peps.json
57+
json_peps = create_pep_json(peps)
58+
Path(path, "peps.json").write_text(json_peps, encoding="utf-8")
59+
os.makedirs(os.path.join(path, "api"), exist_ok=True)
60+
Path(path, "api", "peps.json").write_text(json_peps, encoding="utf-8")
61+
62+
5563
def create_pep_zero(app: Sphinx, env: BuildEnvironment, docnames: list[str]) -> None:
56-
peps = _parse_peps()
64+
peps = _parse_peps(Path(app.srcdir))
5765

5866
pep0_text = writer.PEPZeroWriter().write_pep0(peps, builder=env.settings["builder"])
5967
pep0_path = subindices.update_sphinx("pep-0000", pep0_text, docnames, env)
6068
peps.append(parser.PEP(pep0_path))
6169

6270
subindices.generate_subindices(SUBINDICES_BY_TOPIC, peps, docnames, env)
6371

64-
# Create peps.json
65-
json_path = Path(app.outdir, "api", "peps.json").resolve()
66-
json_path.parent.mkdir(exist_ok=True)
67-
json_path.write_text(create_pep_json(peps), encoding="utf-8")
72+
write_peps_json(peps, Path(app.outdir))

pep_sphinx_extensions/pep_zero_generator/subindices.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from __future__ import annotations
44

5+
import os
56
from pathlib import Path
67
from typing import TYPE_CHECKING
78

@@ -14,8 +15,7 @@
1415

1516

1617
def update_sphinx(filename: str, text: str, docnames: list[str], env: BuildEnvironment) -> Path:
17-
file_path = Path(f"{filename}.rst").resolve()
18-
file_path.parent.mkdir(parents=True, exist_ok=True)
18+
file_path = Path(env.srcdir, f"{filename}.rst")
1919
file_path.write_text(text, encoding="utf-8")
2020

2121
# Add to files for builder
@@ -32,6 +32,9 @@ def generate_subindices(
3232
docnames: list[str],
3333
env: BuildEnvironment,
3434
) -> None:
35+
# create topic directory
36+
os.makedirs(os.path.join(env.srcdir, "topic"), exist_ok=True)
37+
3538
# Create sub index page
3639
generate_topic_contents(docnames, env)
3740

pep_sphinx_extensions/pep_zero_generator/writer.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,8 @@
55
from typing import TYPE_CHECKING
66
import unicodedata
77

8-
from pep_sphinx_extensions.pep_processor.transforms.pep_headers import (
9-
ABBREVIATED_STATUSES,
10-
ABBREVIATED_TYPES,
11-
)
8+
from pep_sphinx_extensions.pep_processor.transforms.pep_headers import ABBREVIATED_STATUSES
9+
from pep_sphinx_extensions.pep_processor.transforms.pep_headers import ABBREVIATED_TYPES
1210
from pep_sphinx_extensions.pep_zero_generator.constants import DEAD_STATUSES
1311
from pep_sphinx_extensions.pep_zero_generator.constants import STATUS_ACCEPTED
1412
from pep_sphinx_extensions.pep_zero_generator.constants import STATUS_ACTIVE
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from pathlib import Path
2+
3+
PEP_ROOT = Path(__file__, "..", "..", "..").resolve()
Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
from pathlib import Path
1+
import datetime as dt
22

33
from pep_sphinx_extensions.pep_processor.transforms import pep_footer
44

5+
from ...conftest import PEP_ROOT
6+
57

68
def test_add_source_link():
7-
out = pep_footer._add_source_link(Path("pep-0008.txt"))
9+
out = pep_footer._add_source_link(PEP_ROOT / "pep-0008.txt")
810

911
assert "https://github.com/python/peps/blob/main/pep-0008.txt" in str(out)
1012

1113

1214
def test_add_commit_history_info():
13-
out = pep_footer._add_commit_history_info(Path("pep-0008.txt"))
15+
out = pep_footer._add_commit_history_info(PEP_ROOT / "pep-0008.txt")
1416

1517
assert str(out).startswith(
1618
"<paragraph>Last modified: "
@@ -21,7 +23,7 @@ def test_add_commit_history_info():
2123

2224

2325
def test_add_commit_history_info_invalid():
24-
out = pep_footer._add_commit_history_info(Path("pep-not-found.txt"))
26+
out = pep_footer._add_commit_history_info(PEP_ROOT / "pep-not-found.rst")
2527

2628
assert str(out) == "<paragraph/>"
2729

@@ -31,4 +33,4 @@ def test_get_last_modified_timestamps():
3133

3234
assert len(out) >= 585
3335
# Should be a Unix timestamp and at least this
34-
assert out["pep-0008.txt"] >= 1643124055
36+
assert dt.datetime.fromisoformat(out["pep-0008"]).timestamp() >= 1643124055

pep_sphinx_extensions/tests/pep_zero_generator/test_parser.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
from pathlib import Path
2-
31
import pytest
42

53
from pep_sphinx_extensions.pep_zero_generator import parser
@@ -19,29 +17,31 @@
1917
)
2018
from pep_sphinx_extensions.pep_zero_generator.parser import _Author
2119

20+
from ..conftest import PEP_ROOT
21+
2222

2323
def test_pep_repr():
24-
pep8 = parser.PEP(Path("pep-0008.txt"))
24+
pep8 = parser.PEP(PEP_ROOT / "pep-0008.txt")
2525

2626
assert repr(pep8) == "<PEP 0008 - Style Guide for Python Code>"
2727

2828

2929
def test_pep_less_than():
30-
pep8 = parser.PEP(Path("pep-0008.txt"))
31-
pep3333 = parser.PEP(Path("pep-3333.txt"))
30+
pep8 = parser.PEP(PEP_ROOT / "pep-0008.txt")
31+
pep3333 = parser.PEP(PEP_ROOT / "pep-3333.txt")
3232

3333
assert pep8 < pep3333
3434

3535

3636
def test_pep_equal():
37-
pep_a = parser.PEP(Path("pep-0008.txt"))
38-
pep_b = parser.PEP(Path("pep-0008.txt"))
37+
pep_a = parser.PEP(PEP_ROOT / "pep-0008.txt")
38+
pep_b = parser.PEP(PEP_ROOT / "pep-0008.txt")
3939

4040
assert pep_a == pep_b
4141

4242

4343
def test_pep_details(monkeypatch):
44-
pep8 = parser.PEP(Path("pep-0008.txt"))
44+
pep8 = parser.PEP(PEP_ROOT / "pep-0008.txt")
4545

4646
assert pep8.details == {
4747
"authors": "Guido van Rossum, Barry Warsaw, Nick Coghlan",
@@ -106,7 +106,7 @@ def test_parse_authors_invalid():
106106
)
107107
def test_abbreviate_type_status(test_type, test_status, expected):
108108
# set up dummy PEP object and monkeypatch attributes
109-
pep = parser.PEP(Path("pep-0008.txt"))
109+
pep = parser.PEP(PEP_ROOT / "pep-0008.txt")
110110
pep.pep_type = test_type
111111
pep.status = test_status
112112

pep_sphinx_extensions/tests/pep_zero_generator/test_pep_index_generator.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
from pathlib import Path
2-
31
from pep_sphinx_extensions.pep_zero_generator import parser, pep_index_generator
42

3+
from ..conftest import PEP_ROOT
4+
55

66
def test_create_pep_json():
7-
peps = [parser.PEP(Path("pep-0008.txt"))]
7+
peps = [parser.PEP(PEP_ROOT / "pep-0008.txt")]
88

99
out = pep_index_generator.create_pep_json(peps)
1010

0 commit comments

Comments
 (0)