Skip to content

All PEPs: Move to peps/ folder #3418

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Sep 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1,310 changes: 655 additions & 655 deletions .github/CODEOWNERS

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .github/PULL_REQUEST_TEMPLATE/Add a new PEP.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ If your PEP is not Standards Track, remove the corresponding section.
## Basic requirements (all PEP Types)

* [ ] Read and followed [PEP 1](https://peps.python.org/1) & [PEP 12](https://peps.python.org/12)
* [ ] File created from the [latest PEP template](https://github.com/python/peps/blob/main/pep-0012/pep-NNNN.rst?plain=1)
* [ ] File created from the [latest PEP template](https://github.com/python/peps/blob/main/peps/pep-0012/pep-NNNN.rst?plain=1)
* [ ] PEP has next available number, & set in filename (``pep-NNNN.rst``), PR title (``PEP 123: <Title of PEP>``) and ``PEP`` header
* [ ] Title clearly, accurately and concisely describes the content in 79 characters or less
* [ ] Core dev/PEP editor listed as ``Author`` or ``Sponsor``, and formally confirmed their approval
Expand Down
28 changes: 17 additions & 11 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
coverage.xml
pep-0000.txt
# PEPs
pep-0000.rst
pep-????.html
peps.rss
topic
/build

# Bytecode
__pycache__
*.pyc
*.pyo
*.py[co]

# Editors
*~
*env
.coverage
.tox
.idea
.vscode
*.swp
/build
/package
/topic

# Tests
coverage.xml
.coverage
.tox

# Virtual environments
*env
/venv
80 changes: 25 additions & 55 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,12 @@ repos:
hooks:
- id: rst-backticks
name: "Check RST: No single backticks"
files: '^pep-\d+\.(rst|txt)$'
types: [text]

- id: rst-inline-touching-normal
name: "Check RST: No backticks touching text"
files: '^pep-\d+\.(rst|txt)$'
types: [text]

- id: rst-directive-colons
name: "Check RST: 2 colons after directives"
files: '^pep-\d+\.(rst|txt)$'
types: [text]

# Manual codespell check
- repo: https://github.com/codespell-project/codespell
Expand All @@ -112,152 +108,126 @@ repos:
# files: "^pep-\d{4}\.(rst|txt)$"
# require_serial: true

- id: check-no-tabs
name: "Check tabs not used in PEPs"
language: pygrep
entry: '\t'
files: '^pep-\d+\.(rst|txt)$'
types: [text]

- id: check-required-headers
name: "PEPs must have all required headers"
language: pygrep
entry: '(?-m:^PEP:(?=[\s\S]*\nTitle:)(?=[\s\S]*\nAuthor:)(?=[\s\S]*\nStatus:)(?=[\s\S]*\nType:)(?=[\s\S]*\nContent-Type:)(?=[\s\S]*\nCreated:))'
args: ['--negate', '--multiline']
files: '^pep-\d+\.(rst|txt)$'
types: [text]
files: '^peps/pep-\d+\.rst$'

- id: check-header-order
name: "PEP header order must follow PEP 12"
language: pygrep
entry: '^PEP:[^\n]+\nTitle:[^\n]+\n(Version:[^\n]+\n)?(Last-Modified:[^\n]+\n)?Author:[^\n]+\n( +\S[^\n]+\n)*(Sponsor:[^\n]+\n)?((PEP|BDFL)-Delegate:[^\n]*\n)?(Discussions-To:[^\n]*\n)?Status:[^\n]+\nType:[^\n]+\n(Topic:[^\n]+\n)?Content-Type:[^\n]+\n(Requires:[^\n]+\n)?Created:[^\n]+\n(Python-Version:[^\n]*\n)?(Post-History:[^\n]*\n( +\S[^\n]*\n)*)?(Replaces:[^\n]+\n)?(Superseded-By:[^\n]+\n)?(Resolution:[^\n]*\n)?\n'
args: ['--negate', '--multiline']
files: '^pep-\d+\.(rst|txt)$'
types: [text]
files: '^peps/pep-\d+\.rst$'

- id: validate-pep-number
name: "'PEP' header must be a number 1-9999"
language: pygrep
entry: '(?-m:^PEP:(?:(?! +(0|[1-9][0-9]{0,3})\n)))'
args: ['--multiline']
files: '^pep-\d+\.(rst|txt)$'
types: [text]
files: '^peps/pep-\d+\.rst$'

- id: validate-title
name: "'Title' must be 1-79 characters"
language: pygrep
entry: '(?<=\n)Title:(?:(?! +\S.{1,78}\n(?=[A-Z])))'
args: ['--multiline']
files: '^pep-\d+\.(rst|txt)$'
exclude: '^pep-(0499)\.(rst|txt)$'
types: [text]
files: '^peps/pep-\d+\.rst$'
exclude: '^peps/pep-(0499)\.rst$'

- id: validate-author
name: "'Author' must be list of 'Name <[email protected]>, ...'"
language: pygrep
entry: '(?<=\n)Author:(?:(?!((( +|\n {1,8})[^!#$%&()*+,/:;<=>?@\[\\\]\^_`{|}~]+( <[\w!#$%&''*+\-/=?^_{|}~.]+(@| at )[\w\-.]+\.[A-Za-z0-9]+>)?)(,|(?=\n[^ ])))+\n(?=[A-Z])))'
args: [--multiline]
files: '^pep-\d+\.(rst|txt)$'
types: [text]
args: ["--multiline"]
files: '^peps/pep-\d+\.rst$'

- id: validate-sponsor
name: "'Sponsor' must have format 'Name <[email protected]>'"
language: pygrep
entry: '^Sponsor:(?: (?! *[^!#$%&()*+,/:;<=>?@\[\\\]\^_`{|}~]+( <[\w!#$%&''*+\-/=?^_{|}~.]+(@| at )[\w\-.]+\.[A-Za-z0-9]+>)?$))'
files: '^pep-\d+\.(rst|txt)$'
types: [text]
files: '^peps/pep-\d+\.rst$'

- id: validate-delegate
name: "'Delegate' must have format 'Name <[email protected]>'"
language: pygrep
entry: '^(PEP|BDFL)-Delegate: (?:(?! *[^!#$%&()*+,/:;<=>?@\[\\\]\^_`{|}~]+( <[\w!#$%&''*+\-/=?^_{|}~.]+(@| at )[\w\-.]+\.[A-Za-z0-9]+>)?$))'
files: '^pep-\d+\.(rst|txt)$'
exclude: '^pep-(0451)\.(rst|txt)$'
types: [text]
files: '^peps/pep-\d+\.rst$'
exclude: '^peps/pep-(0451)\.rst$'

- id: validate-discussions-to
name: "'Discussions-To' must be a thread URL"
language: pygrep
entry: '^Discussions-To: (?:(?!([\w\-]+@(python\.org|googlegroups\.com))|https://((discuss\.python\.org/t/([\w\-]+/)?\d+/?)|(mail\.python\.org/pipermail/[\w\-]+/\d{4}-[A-Za-z]+/[A-Za-z0-9]+\.html)|(mail\.python\.org/archives/list/[\w\-]+@python\.org/thread/[A-Za-z0-9]+/?))$))'
files: '^pep-\d+\.(rst|txt)$'
types: [text]
files: '^peps/pep-\d+\.rst$'

- id: validate-status
name: "'Status' must be a valid PEP status"
language: pygrep
entry: '^Status:(?:(?! +(Draft|Withdrawn|Rejected|Accepted|Final|Active|Provisional|Deferred|Superseded|April Fool!)$))'
files: '^pep-\d+\.(rst|txt)$'
types: [text]
files: '^peps/pep-\d+\.rst$'

- id: validate-type
name: "'Type' must be a valid PEP type"
language: pygrep
entry: '^Type:(?:(?! +(Standards Track|Informational|Process)$))'
files: '^pep-\d+\.(rst|txt)$'
types: [text]
files: '^peps/pep-\d+\.rst$'

- id: validate-topic
name: "'Topic' must be for a valid sub-index"
language: pygrep
entry: '^Topic:(?:(?! +(Governance|Packaging|Typing|Release)(, (Governance|Packaging|Typing|Release))*$))'
files: '^pep-\d+\.(rst|txt)$'
types: [text]
files: '^peps/pep-\d+\.rst$'

- id: validate-content-type
name: "'Content-Type' must be 'text/x-rst'"
language: pygrep
entry: '^Content-Type:(?:(?! +text/x-rst$))'
files: '^pep-\d+\.(rst|txt)$'
types: [text]
files: '^peps/pep-\d+\.rst$'

- id: validate-pep-references
name: "`Requires`/`Replaces`/`Superseded-By` must be 'NNN' PEP IDs"
language: pygrep
entry: '^(Requires|Replaces|Superseded-By):(?:(?! *( (0|[1-9][0-9]{0,3})(,|$))+$))'
files: '^pep-\d+\.(rst|txt)$'
types: [text]
files: '^peps/pep-\d+\.rst$'

- id: validate-created
name: "'Created' must be a 'DD-mmm-YYYY' date"
language: pygrep
entry: '^Created:(?:(?! +([0-2][0-9]|(3[01]))-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(199[0-9]|20[0-9][0-9])$))'
files: '^pep-\d+\.(rst|txt)$'
types: [text]
files: '^peps/pep-\d+\.rst$'

- id: validate-python-version
name: "'Python-Version' must be a 'X.Y[.Z]` version"
language: pygrep
entry: '^Python-Version:(?:(?! *( [1-9]\.([0-9][0-9]?|x)(\.[1-9][0-9]?)?(,|$))+$))'
files: '^pep-\d+\.(rst|txt)$'
types: [text]
files: '^peps/pep-\d+\.rst$'

- id: validate-post-history
name: "'Post-History' must be '`DD-mmm-YYYY <Thread URL>`__, ...'"
language: pygrep
entry: '(?<=\n)Post-History:(?:(?! ?\n|((( +|\n {1,14})(([0-2][0-9]|(3[01]))-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(199[0-9]|20[0-9][0-9])|`([0-2][0-9]|(3[01]))-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(199[0-9]|20[0-9][0-9]) <https://((discuss\.python\.org/t/([\w\-]+/)?\d+(?:/\d+/|/?))|(mail\.python\.org/pipermail/[\w\-]+/\d{4}-[A-Za-z]+/[A-Za-z0-9]+\.html)|(mail\.python\.org/archives/list/[\w\-]+@python\.org/thread/[A-Za-z0-9]+/?(#[A-Za-z0-9]+)?))>`__)(,|(?=\n[^ ])))+\n(?=[A-Z\n]))))'
args: [--multiline]
files: '^pep-\d+\.(rst|txt)$'
types: [text]
files: '^peps/pep-\d+\.rst$'

- id: validate-resolution
name: "'Resolution' must be a direct thread/message URL"
language: pygrep
entry: '(?<!\n\n)(?<=\n)Resolution: (?:(?!https://((discuss\.python\.org/t/([\w\-]+/)?\d+(/\d+)?/?)|(mail\.python\.org/pipermail/[\w\-]+/\d{4}-[A-Za-z]+/[A-Za-z0-9]+\.html)|(mail\.python\.org/archives/list/[\w\-]+@python\.org/(message|thread)/[A-Za-z0-9]+/?(#[A-Za-z0-9]+)?))\n))'
args: ['--multiline']
files: '^pep-\d+\.(rst|txt)$'
types: [text]
files: '^peps/pep-\d+\.rst$'

- id: check-direct-pep-links
name: "Check that PEPs aren't linked directly"
language: pygrep
entry: '(dev/peps|peps\.python\.org)/pep-\d+'
files: '^pep-\d+\.(rst|txt)$'
exclude: '^pep-(0009|0287|0676|0684|8001)\.(rst|txt)$'
types: [text]
files: '^peps/pep-\d+\.rst$'
exclude: '^peps/pep-(0009|0287|0676|0684|8001)\.rst$'

- id: check-direct-rfc-links
name: "Check that RFCs aren't linked directly"
language: pygrep
entry: '(rfc-editor\.org|ietf\.org)/[\.\-_\?\&\#\w/]*[Rr][Ff][Cc][\-_]?\d+'
files: '\.(rst|txt)$'
types: [text]
types: ['rst']
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ OUTPUT_DIR = build
SPHINXERRORHANDLING = -W --keep-going -w sphinx-warnings.txt

ALLSPHINXOPTS = -b $(BUILDER) -j $(JOBS) \
$(SPHINXOPTS) $(SPHINXERRORHANDLING) . $(OUTPUT_DIR) $(SOURCES)
$(SPHINXOPTS) $(SPHINXERRORHANDLING) peps $(OUTPUT_DIR) $(SOURCES)

## html to render PEPs to "pep-NNNN.html" files
.PHONY: html
Expand Down
2 changes: 1 addition & 1 deletion build.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def create_index_file(html_root: Path, builder: str) -> None:
args = create_parser()

root_directory = Path(__file__).resolve().parent
source_directory = root_directory
source_directory = root_directory / "peps"
build_directory = root_directory / args.output_dir

# builder configuration
Expand Down
8 changes: 4 additions & 4 deletions check-peps.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
from __future__ import annotations

import datetime as dt
import itertools
import re
import sys
from pathlib import Path
Expand All @@ -32,7 +31,8 @@


# get the directory with the PEP sources
PEP_ROOT = Path(__file__).resolve().parent
ROOT_DIR = Path(__file__).resolve().parent
PEP_ROOT = ROOT_DIR / "peps"

# See PEP 12 for the order
# Note we retain "BDFL-Delegate"
Expand Down Expand Up @@ -101,7 +101,7 @@ def check(filenames: Sequence[str] = (), /) -> int:
if filenames:
filenames = map(Path, filenames)
else:
filenames = itertools.chain(PEP_ROOT.glob("pep-????.txt"), PEP_ROOT.glob("pep-????.rst"))
filenames = PEP_ROOT.glob("pep-????.rst")
if (count := sum(map(check_file, filenames))) > 0:
s = "s" * (count != 1)
print(f"check-peps failed: {count} error{s}", file=sys.stderr)
Expand Down Expand Up @@ -207,7 +207,7 @@ def check_direct_links(line_num: int, line: str) -> MessageIterator:


def _output_error(filename: Path, lines: Sequence[str], errors: Iterable[Message]) -> int:
relative_filename = filename.relative_to(PEP_ROOT)
relative_filename = filename.relative_to(ROOT_DIR)
err_count = 0
for line_num, msg in errors:
err_count += 1
Expand Down
8 changes: 4 additions & 4 deletions docs/rendering_system.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ to `PEP 676 <https://peps.python.org/pep-0676/>`__.

Configuration is stored in three files:

- ``conf.py`` contains the majority of the Sphinx configuration
- ``contents.rst`` contains the compulsory table of contents directive
- ``peps/conf.py`` contains the majority of the Sphinx configuration
- ``peps/contents.rst`` contains the compulsory table of contents directive
- ``pep_sphinx_extensions/pep_theme/theme.conf`` sets the Pygments themes

The configuration:

- registers the custom Sphinx extension
- sets both ``.txt`` and ``.rst`` suffixes to be parsed as PEPs
- sets the ``.rst`` suffix to be parsed as PEPs
- tells Sphinx which source files to use
- registers the PEP theme, maths renderer, and template
- disables some default settings that are covered in the extension
Expand All @@ -35,7 +35,7 @@ The configuration:
----------------

``build.py`` manages the rendering process.
Usage is covered in :doc:`build`.
Usage is covered in `Building PEPs Locally <./build.rst>`_.


3. Extension
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from pathlib import Path

from docutils import nodes
from docutils.frontend import OptionParser
from sphinx.builders.html import StandaloneHTMLBuilder
Expand Down Expand Up @@ -31,10 +29,6 @@ def get_doc_context(self, docname: str, body: str, _metatags: str) -> dict:
except KeyError:
title = ""

# source filename
file_is_rst = Path(self.env.srcdir, docname + ".rst").exists()
source_name = f"{docname}.rst" if file_is_rst else f"{docname}.txt"

# local table of contents
toc_tree = self.env.tocs[docname].deepcopy()
if len(toc_tree) and len(toc_tree[0]) > 1:
Expand All @@ -46,7 +40,7 @@ def get_doc_context(self, docname: str, body: str, _metatags: str) -> dict:
else:
toc = "" # PEPs with no sections -- 9, 210

return {"title": title, "sourcename": source_name, "toc": toc, "body": body}
return {"title": title, "toc": toc, "body": body}


class DirectoryBuilder(FileBuilder):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def apply(self) -> None:

def _add_source_link(pep_source_path: Path) -> nodes.paragraph:
"""Add link to source text on VCS (GitHub)"""
source_link = f"https://github.com/python/peps/blob/main/{pep_source_path.name}"
source_link = f"https://github.com/python/peps/blob/main/peps/{pep_source_path.name}"
link_node = nodes.reference("", source_link, refuri=source_link)
return nodes.paragraph("", "Source: ", link_node)

Expand All @@ -79,9 +79,12 @@ def _get_last_modified_timestamps():
return {}
all_modified = ret.stdout

# remove "peps/" prefix from file names
all_modified = all_modified.replace("\npeps/", "\n")

# set up the dictionary with the *current* files
peps_dir = Path(__file__, "..", "..", "..", "..").resolve()
last_modified = {path.stem: "" for path in peps_dir.glob("pep-????.???") if path.suffix in {".txt", ".rst"}}
peps_dir = Path(__file__, "..", "..", "..", "..", "peps").resolve()
last_modified = {path.stem: "" for path in peps_dir.glob("pep-????.rst")}

# iterate through newest to oldest, updating per file timestamps
change_sets = all_modified.removeprefix("#").split("#")
Expand Down
4 changes: 2 additions & 2 deletions pep_sphinx_extensions/pep_theme/templates/page.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ <h1>Python Enhancement Proposals</h1>
<h2>Contents</h2>
{{ toc }}
<br>
{%- if not sourcename.startswith(("pep-0000", "topic")) %}
<a id="source" href="https://github.com/python/peps/blob/main/{{sourcename}}">Page Source (GitHub)</a>
{%- if not pagename.startswith(("pep-0000", "topic")) %}
<a id="source" href="https://github.com/python/peps/blob/main/peps/{{pagename}}.rst">Page Source (GitHub)</a>
{%- endif %}
</nav>
</section>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def _parse_peps(path: Path) -> list[parser.PEP]:
continue # Skip directories etc.
if file_path.match("pep-0000*"):
continue # Skip pre-existing PEP 0 files
if file_path.match("pep-????.???") and file_path.suffix in {".txt", ".rst"}:
if file_path.match("pep-????.rst"):
pep = parser.PEP(path.joinpath(file_path).absolute())
peps.append(pep)

Expand Down
2 changes: 1 addition & 1 deletion pep_sphinx_extensions/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from pathlib import Path

_ROOT_PATH = Path(__file__, "..", "..", "..").resolve()
PEP_ROOT = _ROOT_PATH
PEP_ROOT = _ROOT_PATH / "peps"

# Import "check-peps.py" as "check_peps"
CHECK_PEPS_PATH = _ROOT_PATH / "check-peps.py"
Expand Down
Loading