Library / SDK
python/peps avatar
python/peps

python/peps: The Repository Behind Every Python Standard

Python Enhancement Proposals

5,011 stars1,811 forksreStructuredTextLicense varies

At a glance

What is it?
The python/peps repository is the source of truth for Python Enhancement Proposals, rendered to peps.python.org by Sphinx. It is a documentation and governance toolchain, not a library, and adopting it means adopting a build pipeline.
Who is it for?
Adopt python/peps if you are writing, reviewing or mirroring Python standards, or if you need the PEP corpus as build input. Do not adopt it expecting an importable library: there is no package to install, only a Sphinx build that emits HTML.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly reStructuredText, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What python/peps Actually Contains

This repository is the working tree for Python Enhancement Proposals. The README states the PEPs in the repo are published automatically at https://peps.python.org/, and that the PEP Index (PEP 0) is generated from the metadata headers in the other PEPs. That single sentence defines the project's shape: the files under peps/ are the input, and the website is a build artifact.

The audience is narrow and specific. PEP authors, Python core developers, and anyone who needs to mirror or query the PEP corpus. It is not a library you import, and nothing in the repository layout suggests a distributable package. The top level holds build.py, check-peps.py, a Makefile, a Sphinx extension package (pep_sphinx_extensions), a peps/ directory of documents, and infra/ and release_management/ directories. The primary language is reStructuredText, which is the format the proposals themselves are written in.

One consequence is easy to miss. Because PEP 0 is generated from metadata headers rather than hand-edited, a malformed header does not just break one page. It can change the index. The README warns against committing reStructuredText syntax errors that cause PEP generation to fail, which tells you the maintainers treat the build as a correctness check, not a convenience.

How Sphinx Turns reStructuredText Into peps.python.org

The mechanism is a Sphinx build with a custom extension package. The Makefile sets BUILDDIR = build, BUILDER = html, and runs sphinx-build with --fail-on-warning --keep-going --warning-file sphinx-warnings.txt against the peps directory as the source. The comment in the Makefile notes the build synchronises with the render.yml deploy step, so the same target that runs locally is the one that feeds the site.

Warnings are treated as failures. That flag combination is the most consequential design choice in the file: a stray reference or a malformed directive stops the build rather than producing a subtly wrong page. For contributors this is useful feedback. For anyone scripting a build in CI, it means you cannot ignore the exit code.

Search is handled separately. requirements.txt pulls in pagefind[bin] >= 1.5.0 with the comment "For search", and the Makefile exposes a search target that runs pagefind against the build directory. The dirhtml target renders PEPs into pep-NNNN directories with index.html files, then moves build/404/index.html to build/404.html. So the published site is not a flat set of pep-NNNN.html files; the html and dirhtml targets produce different URL layouts, and the Makefile keeps both.

Dependency pinning matters here. requirements.txt requires Sphinx >= 8.2, pygments >= 2.21, sphinx-notfound-page >= 1.0.2, and docutils < 0.22, with an inline note that 0.22 causes build errors. That upper bound is the kind of constraint you inherit when you build the corpus yourself.

Building the PEPs Locally and Rendering Your First Page

The README gives the local render steps directly, and the Makefile wraps them. The documented path is a fresh, activated virtual environment, then the requirements install, then make html. The README notes that if you do not have make, you can run python build.py instead, and that the output HTML lands under the build directory.

Start by installing the build requirements into a virtual environment:

bash
python -m pip install -U -r requirements.txt

Then render the whole corpus. The Makefile's html target depends on a venv target and invokes sphinx-build with the warning flags described above, so expect the command to fail loudly if any PEP has a syntax problem:

bash
make html

If make is unavailable on your platform, the README names the fallback:

bash
python build.py

After a successful run, open build/index.html. The Makefile provides a shortcut that renders and then opens the index in your browser:

bash
make htmlview

For iterative editing there is a live-rebuild target. It switches the builder to sphinx-autobuild, ignores a few paths, and serves on port 55302, which the Makefile comment describes as an arbitrarily selected ephemeral port chosen to avoid conflicts:

bash
make htmllive

One practical note before you commit: the README asks contributors not to commit changes with reStructuredText syntax errors that cause PEP generation to fail. Running make html first is the cheapest way to honour that.

The Checks That Will Reject Your Pull Request

Beyond rendering, the repository ships a linting layer. The README points to a pre-commit suite that can check and fix common linting and spelling issues, either on demand or automatically as you commit, with details in CONTRIBUTING.rst. The .pre-commit-config.yaml and .codespellrc files at the top level are the configuration for that suite, and .codespell/ is a directory of spelling data.

There is also a dedicated checker. check-peps.py sits at the repository root, and its name is the clearest statement of intent: PEP files have structural rules that go past Sphinx's parser. The README does not enumerate those rules, so the script itself and CONTRIBUTING.rst are where you would look. That is a real documentation gap for a first-time contributor, and it is worth saying plainly rather than pretending the README covers it.

Python-side linting is configured in pyproject.toml, which targets py311 and selects the pycodestyle, pyflakes, isort, flake8-pytest-style, pyupgrade and flake8-2020 rule sets, ignoring E501 (line too long). Tests run under pytest, declared in requirements.txt as pytest>=9 with pytest-cov, and .pytest.toml and tox.ini are present at the root. If you plan to change the Sphinx extensions or the build scripts rather than the prose, that is the toolchain you are signing up for.

Previews, Canonical Links and the PEP API

Reviewing a PEP change without building it locally is possible. The README states that for every pull request the project automatically creates a rendered preview using Read the Docs, reachable from the merge box: expand "Show all checks", find the line for docs/readthedocs.org:pep-previews, and click Details. The .readthedocs.yaml file at the top level is the configuration behind that.

Link stability is handled deliberately. The README describes the canonical form of PEP links as zero-padded, such as https://peps.python.org/pep-0008/, with shortcut redirects, so https://peps.python.org/8 redirects to the canonical link. If you cite PEPs in documentation or tooling, use the padded form; the shortcuts exist for humans, not as a stable identifier.

For programmatic access, the README points to data files under https://peps.python.org/api/. It does not describe their schemas or update cadence. That is a limitation worth flagging: the API is advertised, not specified, so anyone building on it should inspect the files and pin to the shapes they find rather than assuming a contract.

Where python/peps Is the Wrong Tool

The most common mistake is treating this as a Python package. There is no installable distribution in the repository: requirements.txt lists build dependencies for Sphinx, not a library, and the top-level entries are build scripts, configuration and prose. If your goal is to read PEP 8, open the website. Cloning the repository to consult a style guide adds a Sphinx toolchain to a task that needs a browser.

A second boundary is maintainer status. The repository is not archived, and the last push was on 2026-09-22, so it is live. But activity here is editorial: PEPs move at the pace of the Python development process, not at the pace of a software release cycle. The repository lists no releases, which fits a project whose artifacts are documents and a rendered site rather than versioned packages.

Third, the build is strict by design. If you vendor the PEP corpus into your own pipeline and want lenient rendering, the --fail-on-warning flag in the Makefile is the opposite of what you want, and you would be fighting the project's own configuration. Similarly, the docutils < 0.22 pin in requirements.txt means you cannot simply take the newest docutils; the file records that 0.22 causes build errors.

Alternatives and How Their Approach Differs

The obvious alternative for reading the standards is not a repository at all: the published site at peps.python.org, including the shortcut redirects and the API data files. That path costs nothing to set up and always reflects the current state, but it gives you no local diff, no offline copy, and no way to render a proposal you are drafting before it exists upstream.

Within the Python documentation world, the closest structural analogue is the CPython documentation build, which also uses Sphinx with reStructuredText sources and a Makefile. The difference is scope and validation: this repository renders standalone proposals with a custom extension package, a generated index built from metadata headers, a dedicated check-peps.py, and warnings promoted to build failures. A general Sphinx documentation project typically does not generate its own index from document headers, and rarely fails the build on every warning.

If you only need the text of the proposals, fetching the raw reStructuredText files is a lighter option than reproducing the build, at the cost of losing the rendered cross-references, the generated index and the search index that pagefind produces.

Maintenance, Upgrades and Licence Status

The upgrade surface is small but sharp. requirements.txt pins Sphinx >= 8.2 and docutils < 0.22, and the inline comment records that 0.22 breaks the build. Anyone mirroring the corpus inherits that ceiling and should test a docutils bump against the full build rather than assuming compatibility. The Makefile's SPHINXERRORHANDLING variable is the other thing to keep aligned: if you change it, you change what counts as a passing build.

The pre-commit suite adds a second maintenance axis, since .codespellrc and .pre-commit-config.yaml drift as spelling dictionaries and hook versions move. For a project whose content changes through pull requests from many authors, that is the price of consistent prose.

The repository does not state a licence in the files provided. PEP 1 is the documented starting point for how PEPs are written and what they are for, and it is the right place to check the terms that apply to the documents themselves. This is a factual gap, not a legal opinion: confirm the licence from the repository before redistributing the corpus in a product.

Editorial conclusion

Adopt python/peps if you are writing, reviewing or mirroring Python standards, or if you need the PEP corpus as build input. Do not adopt it expecting an importable library: there is no package to install, only a Sphinx build that emits HTML. Before your first pull request, run the build locally with make html and confirm the output lands under build, then read CONTRIBUTING.rst for the pre-commit suite, because the README states that PEP generation must not fail on reStructuredText syntax errors.

Frequently asked questions

What are PEPs in Python?

PEP stands for Python Enhancement Proposal. The README directs readers to PEP 1 for the purpose of PEPs and how to write one, and the proposals in this repository are published automatically at peps.python.org.

What do PEPs stand for in Python?

The repository name is Python Enhancement Proposals, which the README expands in its title. PEP 1 is the document the README points to for the purpose of PEPs and the process for writing one.

Is PEP 8 still used?

The repository does not discuss PEP 8's current status. What it does show is that PEP 8 is published at the canonical link https://peps.python.org/pep-0008/, and that the PEP Index in PEP 0 is generated from the metadata headers of the other PEPs.

What is python peps?

It is the repository holding the source of the Python Enhancement Proposals, which the README says are published automatically at https://peps.python.org/. The PEP Index itself, PEP 0, is generated from the metadata headers in the other PEPs.

Official sources

  1. Issues
  2. Project website
  3. python/peps on GitHub
  4. README
For maintainers

Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/python-peps.svg)](https://hysenlabs.com/projects/python-peps)
Community notes

Community notes