diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4f7f3380ee0..b7b9b4e574d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -111,3 +111,12 @@ repos: language: "python" files: '^peps/pep-\d{4}\.rst$' require_serial: true + + # Hook to regenerate release schedules + - id: "regen-schedules" + name: "Regenerate release schedules from python-releases.toml" + entry: "python -m release_engineering update-peps" + language: "python" + files: "^release_engineering/" + pass_filenames: false + require_serial: true diff --git a/Makefile b/Makefile index 988eba44892..68428c22dea 100644 --- a/Makefile +++ b/Makefile @@ -107,6 +107,11 @@ test: venv spellcheck: _ensure-pre-commit $(VENVDIR)/bin/python3 -m pre_commit run --all-files --hook-stage manual codespell +## regen-all to regenerate generated source files +.PHONY: regen-all +regen-all: + $(PYTHON) -m release_engineering update-peps + .PHONY: help help : Makefile @echo "Please use \`make ' where is one of" diff --git a/pep_sphinx_extensions/pep_zero_generator/pep_index_generator.py b/pep_sphinx_extensions/pep_zero_generator/pep_index_generator.py index 2dc3e7ff52d..6fc45a90499 100644 --- a/pep_sphinx_extensions/pep_zero_generator/pep_index_generator.py +++ b/pep_sphinx_extensions/pep_zero_generator/pep_index_generator.py @@ -19,6 +19,7 @@ import json import os +import sys from pathlib import Path from typing import TYPE_CHECKING @@ -26,6 +27,12 @@ from pep_sphinx_extensions.pep_zero_generator import subindices from pep_sphinx_extensions.pep_zero_generator import writer from pep_sphinx_extensions.pep_zero_generator.constants import SUBINDICES_BY_TOPIC +if sys.version_info >= (3, 11): + from release_engineering.generate_release_cycle import create_release_cycle +else: + # this function uses tomllib, which requires Python 3.11+ + def create_release_cycle(): + return '' if TYPE_CHECKING: from sphinx.application import Sphinx @@ -73,3 +80,6 @@ def create_pep_zero(app: Sphinx, env: BuildEnvironment, docnames: list[str]) -> subindices.generate_subindices(SUBINDICES_BY_TOPIC, peps, docnames, env) write_peps_json(peps, Path(app.outdir)) + + release_cycle = create_release_cycle() + app.outdir.joinpath('release-cycle.json').write_text(release_cycle, encoding="utf-8") diff --git a/peps/pep-0569.rst b/peps/pep-0569.rst index fc8d32d73ed..7d9227cd21c 100644 --- a/peps/pep-0569.rst +++ b/peps/pep-0569.rst @@ -51,6 +51,10 @@ Release Schedule 3.8.0 schedule -------------- +.. feature release schedule + +Actual: + - 3.8 development begins: Monday, 2018-01-29 - 3.8.0 alpha 1: Sunday, 2019-02-03 - 3.8.0 alpha 2: Monday, 2019-02-25 @@ -58,51 +62,65 @@ Release Schedule - 3.8.0 alpha 4: Monday, 2019-05-06 - 3.8.0 beta 1: Tuesday, 2019-06-04 (No new features beyond this point.) - - 3.8.0 beta 2: Thursday, 2019-07-04 - 3.8.0 beta 3: Monday, 2019-07-29 - 3.8.0 beta 4: Friday, 2019-08-30 - 3.8.0 candidate 1: Tuesday, 2019-10-01 - 3.8.0 final: Monday, 2019-10-14 +.. end of schedule + Bugfix releases --------------- -- 3.8.1rc1: Tuesday, 2019-12-10 -- 3.8.1: Wednesday, 2019-12-18 -- 3.8.2rc1: Monday, 2020-02-10 -- 3.8.2rc2: Monday, 2020-02-17 -- 3.8.2: Monday, 2020-02-24 -- 3.8.3rc1: Wednesday, 2020-04-29 -- 3.8.3: Wednesday, 2020-05-13 -- 3.8.4rc1: Tuesday, 2020-06-30 -- 3.8.4: Monday, 2020-07-13 -- 3.8.5: Monday, 2020-07-20 (security hotfix) -- 3.8.6rc1: Tuesday, 2020-09-08 -- 3.8.6: Thursday, 2020-09-24 -- 3.8.7rc1: Monday, 2020-12-07 -- 3.8.7: Monday, 2020-12-21 -- 3.8.8rc1: Tuesday, 2021-02-16 -- 3.8.8: Friday, 2021-02-19 -- 3.8.9: Friday, 2021-04-02 (security hotfix) -- 3.8.10: Monday, 2021-05-03 (final regular bugfix release with binary - installers) +.. bugfix release schedule + +Actual: + +- 3.8.1 candidate 1: Tuesday, 2019-12-10 +- 3.8.1 final: Wednesday, 2019-12-18 +- 3.8.2 candidate 1: Monday, 2020-02-10 +- 3.8.2 candidate 2: Monday, 2020-02-17 +- 3.8.2 final: Monday, 2020-02-24 +- 3.8.3 candidate 1: Wednesday, 2020-04-29 +- 3.8.3 final: Wednesday, 2020-05-13 +- 3.8.4 candidate 1: Tuesday, 2020-06-30 +- 3.8.4 final: Monday, 2020-07-13 +- 3.8.5 final: Monday, 2020-07-20 + (security hotfix) +- 3.8.6 candidate 1: Tuesday, 2020-09-08 +- 3.8.6 final: Thursday, 2020-09-24 +- 3.8.7 candidate 1: Monday, 2020-12-07 +- 3.8.7 final: Monday, 2020-12-21 +- 3.8.8 candidate 1: Tuesday, 2021-02-16 +- 3.8.8 final: Friday, 2021-02-19 +- 3.8.9 final: Friday, 2021-04-02 + (security hotfix) +- 3.8.10 final: Monday, 2021-05-03 + (final regular bugfix release with binary installers) + +.. end of schedule Source-only security fix releases --------------------------------- Provided irregularly on an "as-needed" basis until October 7th 2024. -- 3.8.11: Monday, 2021-06-28 -- 3.8.12: Monday, 2021-08-30 -- 3.8.13: Wednesday, 2022-03-16 -- 3.8.14: Tuesday, 2022-09-06 -- 3.8.15: Tuesday, 2022-10-11 -- 3.8.16: Tuesday, 2022-12-06 -- 3.8.17: Tuesday, 2023-06-06 -- 3.8.18: Thursday, 2023-08-24 -- 3.8.19: Tuesday, 2024-03-19 -- 3.8.20: Friday, 2024-09-06 (final security release) +.. security release schedule + +- 3.8.11 final: Monday, 2021-06-28 +- 3.8.12 final: Monday, 2021-08-30 +- 3.8.13 final: Wednesday, 2022-03-16 +- 3.8.14 final: Tuesday, 2022-09-06 +- 3.8.15 final: Tuesday, 2022-10-11 +- 3.8.16 final: Tuesday, 2022-12-06 +- 3.8.17 final: Tuesday, 2023-06-06 +- 3.8.18 final: Thursday, 2023-08-24 +- 3.8.19 final: Tuesday, 2024-03-19 +- 3.8.20 final: Friday, 2024-09-06 + (final security release) + +.. end of schedule Features for 3.8 diff --git a/peps/pep-0596.rst b/peps/pep-0596.rst index e981947a86b..6f709cbdfde 100644 --- a/peps/pep-0596.rst +++ b/peps/pep-0596.rst @@ -40,6 +40,8 @@ Note: the dates below use a 17-month development period that results in a 12-month release cadence between feature versions, as defined by :pep:`602`. +.. feature release schedule + Actual: - 3.9 development begins: Tuesday, 2019-06-04 @@ -59,28 +61,37 @@ Actual: - 3.9.0 candidate 2: Thursday, 2020-09-17 - 3.9.0 final: Monday, 2020-10-05 +.. end of schedule + Bugfix releases --------------- +.. bugfix release schedule + Actual: - 3.9.1 candidate 1: Tuesday, 2020-11-24 - 3.9.1 final: Monday, 2020-12-07 - 3.9.2 candidate 1: Tuesday, 2021-02-16 - 3.9.2 final: Friday, 2021-02-19 -- 3.9.3: Friday, 2021-04-02 (security hotfix; recalled due to bpo-43710) -- 3.9.4: Sunday, 2021-04-04 (ABI compatibility hotfix) -- 3.9.5: Monday, 2021-05-03 -- 3.9.6: Monday, 2021-06-28 -- 3.9.7: Monday, 2021-08-30 -- 3.9.8: Friday, 2021-11-05 (recalled due to bpo-45235) -- 3.9.9: Monday, 2021-11-15 -- 3.9.10: Friday, 2022-01-14 -- 3.9.11: Wednesday, 2022-03-16 -- 3.9.12: Wednesday, 2022-03-23 -- 3.9.13: Tuesday, 2022-05-17 (final regular bugfix release with binary - installers) +- 3.9.3 final: Friday, 2021-04-02 + (security hotfix; recalled due to bpo-43710) +- 3.9.4 final: Sunday, 2021-04-04 + (ABI compatibility hotfix) +- 3.9.5 final: Monday, 2021-05-03 +- 3.9.6 final: Monday, 2021-06-28 +- 3.9.7 final: Monday, 2021-08-30 +- 3.9.8 final: Friday, 2021-11-05 + (recalled due to bpo-45235) +- 3.9.9 final: Monday, 2021-11-15 +- 3.9.10 final: Friday, 2022-01-14 +- 3.9.11 final: Wednesday, 2022-03-16 +- 3.9.12 final: Wednesday, 2022-03-23 +- 3.9.13 final: Tuesday, 2022-05-17 + (final regular bugfix release with binary installers) + +.. end of schedule Source-only security fix releases @@ -88,14 +99,18 @@ Source-only security fix releases Provided irregularly on an "as-needed" basis until October 2025. -- 3.9.14: Tuesday, 2022-09-06 -- 3.9.15: Tuesday, 2022-10-11 -- 3.9.16: Tuesday, 2022-12-06 -- 3.9.17: Tuesday, 2023-06-06 -- 3.9.18: Thursday, 2023-08-24 -- 3.9.19: Tuesday, 2024-03-19 -- 3.9.20: Friday, 2024-09-06 -- 3.9.21: Tuesday, 2024-12-03 +.. security release schedule + +- 3.9.14 final: Tuesday, 2022-09-06 +- 3.9.15 final: Tuesday, 2022-10-11 +- 3.9.16 final: Tuesday, 2022-12-06 +- 3.9.17 final: Tuesday, 2023-06-06 +- 3.9.18 final: Thursday, 2023-08-24 +- 3.9.19 final: Tuesday, 2024-03-19 +- 3.9.20 final: Friday, 2024-09-06 +- 3.9.21 final: Tuesday, 2024-12-03 + +.. end of schedule 3.9 Lifespan diff --git a/peps/pep-0619.rst b/peps/pep-0619.rst index cdb81a2224b..2504a9725e9 100644 --- a/peps/pep-0619.rst +++ b/peps/pep-0619.rst @@ -37,6 +37,8 @@ Note: the dates below use a 17-month development period that results in a 12-month release cadence between feature versions, as defined by :pep:`602`. +.. feature release schedule + Actual: - 3.10 development begins: Monday, 2020-05-18 @@ -56,34 +58,44 @@ Actual: - 3.10.0 candidate 2: Tuesday, 2021-09-07 - 3.10.0 final: Monday, 2021-10-04 +.. end of schedule + Bugfix releases --------------- +.. bugfix release schedule + Actual: -- 3.10.1: Monday, 2021-12-06 -- 3.10.2: Friday, 2022-01-14 -- 3.10.3: Wednesday, 2022-03-16 -- 3.10.4: Thursday, 2022-03-24 -- 3.10.5: Monday, 2022-06-06 -- 3.10.6: Tuesday, 2022-08-02 -- 3.10.7: Tuesday, 2022-09-06 -- 3.10.8: Tuesday, 2022-10-11 -- 3.10.9: Tuesday, 2022-12-06 -- 3.10.10: Wednesday, 2023-02-08 -- 3.10.11: Wednesday, 2023-04-05 (final regular bugfix release with binary - installers) +- 3.10.1 final: Monday, 2021-12-06 +- 3.10.2 final: Friday, 2022-01-14 +- 3.10.3 final: Wednesday, 2022-03-16 +- 3.10.4 final: Thursday, 2022-03-24 +- 3.10.5 final: Monday, 2022-06-06 +- 3.10.6 final: Tuesday, 2022-08-02 +- 3.10.7 final: Tuesday, 2022-09-06 +- 3.10.8 final: Tuesday, 2022-10-11 +- 3.10.9 final: Tuesday, 2022-12-06 +- 3.10.10 final: Wednesday, 2023-02-08 +- 3.10.11 final: Wednesday, 2023-04-05 + (final regular bugfix release with binary installers) + +.. end of schedule Source-only security fix releases --------------------------------- Provided irregularly on an "as-needed" basis until October 2026. -- 3.10.12: Tuesday, 2023-06-06 -- 3.10.13: Thursday, 2023-08-24 -- 3.10.14: Tuesday, 2024-03-19 -- 3.10.15: Saturday, 2024-09-07 -- 3.10.16: Tuesday, 2024-12-03 +.. security release schedule + +- 3.10.12 final: Tuesday, 2023-06-06 +- 3.10.13 final: Thursday, 2023-08-24 +- 3.10.14 final: Tuesday, 2024-03-19 +- 3.10.15 final: Saturday, 2024-09-07 +- 3.10.16 final: Tuesday, 2024-12-03 + +.. end of schedule 3.10 Lifespan ------------- diff --git a/peps/pep-0664.rst b/peps/pep-0664.rst index 8c7c53c054c..55eadec04d9 100644 --- a/peps/pep-0664.rst +++ b/peps/pep-0664.rst @@ -38,6 +38,8 @@ Note: the dates below use a 17-month development period that results in a 12-month release cadence between feature versions, as defined by :pep:`602`. +.. feature release schedule + Actual: - 3.11 development begins: Monday, 2021-05-03 @@ -56,31 +58,41 @@ Actual: - 3.11.0 beta 5: Tuesday, 2022-07-26 - 3.11.0 candidate 1: Monday, 2022-08-08 - 3.11.0 candidate 2: Monday, 2022-09-12 -- 3.11.0 final: Monday, 2022-10-24 +- 3.11.0 final: Monday, 2022-10-24 + +.. end of schedule Bugfix releases --------------- +.. bugfix release schedule + Actual: -- 3.11.1: Tuesday, 2022-12-06 -- 3.11.2: Wednesday, 2023-02-08 -- 3.11.3: Wednesday, 2023-04-05 -- 3.11.4: Tuesday, 2023-06-06 -- 3.11.5: Thursday, 2023-08-24 -- 3.11.6: Monday, 2023-10-02 -- 3.11.7: Monday, 2023-12-04 -- 3.11.8: Tuesday, 2024-02-06 -- 3.11.9: Tuesday, 2024-04-02 (final regular bugfix release with binary - installers) +- 3.11.1 final: Tuesday, 2022-12-06 +- 3.11.2 final: Wednesday, 2023-02-08 +- 3.11.3 final: Wednesday, 2023-04-05 +- 3.11.4 final: Tuesday, 2023-06-06 +- 3.11.5 final: Thursday, 2023-08-24 +- 3.11.6 final: Monday, 2023-10-02 +- 3.11.7 final: Monday, 2023-12-04 +- 3.11.8 final: Tuesday, 2024-02-06 +- 3.11.9 final: Tuesday, 2024-04-02 + (final regular bugfix release with binary installers) + +.. end of schedule Source-only security fix releases --------------------------------- Provided irregularly on an "as-needed" basis until October 2027. -- 3.11.10: Saturday, 2024-09-07 -- 3.11.11: Tuesday, 2024-12-03 +.. security release schedule + +- 3.11.10 final: Saturday, 2024-09-07 +- 3.11.11 final: Tuesday, 2024-12-03 + +.. end of schedule 3.11 Lifespan ------------- diff --git a/peps/pep-0693.rst b/peps/pep-0693.rst index c4895b4bb79..a2a6558c0fa 100644 --- a/peps/pep-0693.rst +++ b/peps/pep-0693.rst @@ -32,6 +32,8 @@ Note: the dates below use a 17-month development period that results in a 12-month release cadence between feature versions, as defined by :pep:`602`. +.. feature release schedule + Actual: - 3.12 development begins: Sunday, 2022-05-08 @@ -50,26 +52,33 @@ Actual: - 3.12.0 candidate 1: Sunday, 2023-08-06 - 3.12.0 candidate 2: Wednesday, 2023-09-06 - 3.12.0 candidate 3: Tuesday, 2023-09-19 -- 3.12.0 final: Monday, 2023-10-02 +- 3.12.0 final: Monday, 2023-10-02 + +.. end of schedule Bugfix releases --------------- +.. bugfix release schedule + Actual: -- 3.12.1: Thursday, 2023-12-07 -- 3.12.2: Tuesday, 2024-02-06 -- 3.12.3: Tuesday, 2024-04-09 -- 3.12.4: Thursday, 2024-06-06 -- 3.12.5: Tuesday, 2024-08-06 -- 3.12.6: Friday, 2024-09-06 -- 3.12.7: Tuesday, 2024-10-01 -- 3.12.8: Tuesday, 2024-12-03 -- 3.12.9: Tuesday, 2025-02-04 +- 3.12.1 final: Thursday, 2023-12-07 +- 3.12.2 final: Tuesday, 2024-02-06 +- 3.12.3 final: Tuesday, 2024-04-09 +- 3.12.4 final: Thursday, 2024-06-06 +- 3.12.5 final: Tuesday, 2024-08-06 +- 3.12.6 final: Friday, 2024-09-06 +- 3.12.7 final: Tuesday, 2024-10-01 +- 3.12.8 final: Tuesday, 2024-12-03 +- 3.12.9 final: Tuesday, 2025-02-04 Expected: -- 3.12.10: Tuesday, 2025-04-08 +- 3.12.10 final: Tuesday, 2025-04-08 + (final regular bugfix release with binary installers) + +.. end of schedule Source-only security fix releases --------------------------------- diff --git a/peps/pep-0719.rst b/peps/pep-0719.rst index f75deeaad49..f713248a19d 100644 --- a/peps/pep-0719.rst +++ b/peps/pep-0719.rst @@ -33,6 +33,8 @@ Note: the dates below use a 17-month development period that results in a 12-month release cadence between feature versions, as defined by :pep:`602`. +.. feature release schedule + Actual: - 3.13 development begins: Monday, 2023-05-22 @@ -51,24 +53,34 @@ Actual: - 3.13.0 candidate 2: Friday, 2024-09-06 - 3.13.0 candidate 3: Tuesday, 2024-10-01 - 3.13.0 final: Monday, 2024-10-07 -- 3.13.1: Tuesday, 2024-12-03 -- 3.13.2: Tuesday, 2025-02-04 + +.. end of schedule Bugfix releases --------------- +.. bugfix release schedule + +Actual: + +- 3.13.1 final: Tuesday, 2024-12-03 +- 3.13.2 final: Tuesday, 2025-02-04 + Expected: -- 3.13.3: Tuesday, 2025-04-08 -- 3.13.4: Tuesday, 2025-06-03 -- 3.13.5: Tuesday, 2025-08-05 -- 3.13.6: Tuesday, 2025-10-07 -- 3.13.7: Tuesday, 2025-12-02 -- 3.13.8: Tuesday, 2026-02-03 -- 3.13.9: Tuesday, 2026-04-07 -- 3.13.10: Tuesday, 2026-06-09 -- 3.13.11: Tuesday, 2026-08-04 -- 3.13.12: Tuesday, 2026-10-06 +- 3.13.3 final: Tuesday, 2025-04-08 +- 3.13.4 final: Tuesday, 2025-06-03 +- 3.13.5 final: Tuesday, 2025-08-05 +- 3.13.6 final: Tuesday, 2025-10-07 +- 3.13.7 final: Tuesday, 2025-12-02 +- 3.13.8 final: Tuesday, 2026-02-03 +- 3.13.9 final: Tuesday, 2026-04-07 +- 3.13.10 final: Tuesday, 2026-06-09 +- 3.13.11 final: Tuesday, 2026-08-04 +- 3.13.12 final: Tuesday, 2026-10-06 + (final regular bugfix release with binary installers) + +.. end of schedule Source-only security fix releases diff --git a/peps/pep-0745.rst b/peps/pep-0745.rst index 6c79ff20b25..bdd7db1f7f9 100644 --- a/peps/pep-0745.rst +++ b/peps/pep-0745.rst @@ -33,6 +33,8 @@ The dates below use a 17-month development period that results in a 12-month release cadence between feature versions, as defined by :pep:`602`. +.. feature release schedule + Actual: - 3.14 development begins: Wednesday, 2024-05-08 @@ -55,6 +57,8 @@ Expected: - 3.14.0 candidate 2: Tuesday, 2025-08-26 - 3.14.0 final: Tuesday, 2025-10-07 +.. end of schedule + Subsequent bugfix releases every two months. diff --git a/release_engineering/LICENCE.rst b/release_engineering/LICENCE.rst new file mode 100644 index 00000000000..d68de666acb --- /dev/null +++ b/release_engineering/LICENCE.rst @@ -0,0 +1,2 @@ +The files in this directory are placed in the public domain or under the +CC0-1.0-Universal license, whichever is more permissive. diff --git a/release_engineering/__init__.py b/release_engineering/__init__.py new file mode 100644 index 00000000000..c6cdee60785 --- /dev/null +++ b/release_engineering/__init__.py @@ -0,0 +1,71 @@ +from __future__ import annotations + +import dataclasses +import datetime as dt +import tomllib +from pathlib import Path + +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import Literal, TypeAlias + + ReleaseState: TypeAlias = Literal['actual', 'expected'] + ReleaseSchedules: TypeAlias = dict[tuple[str, ReleaseState], list['ReleaseInfo']] + +RELEASE_DIR = Path(__file__).resolve().parent +ROOT_DIR = RELEASE_DIR.parent +PEP_ROOT = ROOT_DIR / 'peps' + + +@dataclasses.dataclass(frozen=True, kw_only=True, slots=True) +class PythonReleases: + metadata: dict[str, 'VersionMetadata'] + releases: dict[str, list['ReleaseInfo']] + + +@dataclasses.dataclass(frozen=True, kw_only=True, slots=True) +class VersionMetadata: + """Metadata for a given interpreter version (MAJOR.MINOR).""" + + pep: int + status: str + branch: str + release_manager: str + start_of_development: dt.date + first_release: dt.date + feature_freeze: dt.date + end_of_bugfix: dt.date # a.k.a. security mode or source-only releases + end_of_life: dt.date + + @classmethod + def from_toml(cls, data: dict[str, int | str | dt.date]): + return cls(**{k.replace('-', '_'): v for k, v in data.items()}) + + +@dataclasses.dataclass(frozen=True, kw_only=True, slots=True) +class ReleaseInfo: + """Information about a release.""" + + stage: str + state: ReleaseState + date: dt.date + note: str = '' # optional note / comment, displayed in the schedule + + @property + def schedule_bullet(self): + """Return a formatted bullet point for the schedule list.""" + return f'- {self.stage}: {self.date:%A, %Y-%m-%d}' + + +def load_python_releases() -> PythonReleases: + with open(RELEASE_DIR / 'python-releases.toml', 'rb') as f: + python_releases = tomllib.load(f) + all_metadata = { + v: VersionMetadata.from_toml(metadata) + for v, metadata in python_releases['metadata'].items() + } + all_releases = { + v: [ReleaseInfo(**r) for r in releases] + for v, releases in python_releases['release'].items() + } + return PythonReleases(metadata=all_metadata, releases=all_releases) diff --git a/release_engineering/__main__.py b/release_engineering/__main__.py new file mode 100644 index 00000000000..d6ed83d2542 --- /dev/null +++ b/release_engineering/__main__.py @@ -0,0 +1,21 @@ +from __future__ import annotations + +import argparse + +CMD_UPDATE_PEPS = 'update-peps' +CMD_RELEASE_CYCLE = 'release-cycle' + +PARSER = argparse.ArgumentParser(allow_abbrev=False) +PARSER.add_argument('COMMAND', choices=[CMD_UPDATE_PEPS, CMD_RELEASE_CYCLE]) + +args = PARSER.parse_args() +if args.COMMAND == CMD_UPDATE_PEPS: + from release_engineering.update_release_schedules import update_peps + + update_peps() +elif args.COMMAND == CMD_RELEASE_CYCLE: + from pathlib import Path + + from release_engineering.generate_release_cycle import create_release_cycle + + Path('release-cycle.json').write_text(create_release_cycle(), encoding='utf-8') diff --git a/release_engineering/generate_release_cycle.py b/release_engineering/generate_release_cycle.py new file mode 100644 index 00000000000..0e379b357a7 --- /dev/null +++ b/release_engineering/generate_release_cycle.py @@ -0,0 +1,41 @@ +from __future__ import annotations + +import json + +from release_engineering import load_python_releases + +TYPE_CHECKING = False +if TYPE_CHECKING: + from release_engineering import VersionMetadata + + +def create_release_cycle() -> str: + metadata = load_python_releases().metadata + versions = [v for v in metadata if version_to_tuple(v) >= (2, 6)] + versions.sort(key=version_to_tuple, reverse=True) + if '2.7' in versions: + versions.remove('2.7') + versions.insert(versions.index('3.1'), '2.7') + + release_cycle = {version: version_info(metadata[version]) for version in versions} + return ( + json.dumps(release_cycle, indent=2, sort_keys=False, ensure_ascii=False) + '\n' + ) + + +def version_to_tuple(version: str, /) -> tuple[int, ...]: + return tuple(map(int, version.split('.'))) + + +def version_info(metadata: VersionMetadata, /) -> dict[str, str]: + end_of_life = metadata.end_of_life.isoformat() + if metadata.status != 'end-of-life': + end_of_life = end_of_life.removesuffix('-01') + return { + 'branch': metadata.branch, + 'pep': metadata.pep, + 'status': metadata.status, + 'first_release': metadata.first_release.isoformat(), + 'end_of_life': end_of_life, + 'release_manager': metadata.release_manager, + } diff --git a/release_engineering/python-releases.toml b/release_engineering/python-releases.toml new file mode 100644 index 00000000000..b5421a00bf3 --- /dev/null +++ b/release_engineering/python-releases.toml @@ -0,0 +1,3334 @@ +# This file is placed in the public domain or under the +# CC0-1.0-Universal licence, whichever is more permissive. +# +# This document contains the history of every release of the Python project, +# and specifically the CPython intepreter. The data in this file were initially +# compiled in 2025 by Adam Turner, with information primarily sourced from the +# release PEPs and supplemented by the 'releases' section of www.python.org. +# +# The release schedules for Python 3.8 onwards are created from data in this +# document. After editing this file, run the following command to regenerate +# the relevant PEPs: +# +# python -m release_engineering update-peps +# +# The PEP rendering system, via Sphinx, uses this document to regenerate the +# 'release-cycle' JSON file, found at https://peps.python.org/release-cycle.json. +# This JSON file is intended for public consumption. The format of this TOML +# document is not guaranteed and may change without notice. + +# -- Python 1.6 -------------------------------------------------------------- + +[metadata."1.6"] +pep = 160 +status = "end-of-life" +branch = "" # no branch or tag for 1.6 exists +release-manager = "Fred L. Drake, Jr" +start-of-development = 1999-06-09 +first-release = 2000-09-05 +feature-freeze = 2000-08-03 +end-of-bugfix = 2000-09-05 +end-of-life = 2000-09-05 + +[[release."1.6"]] +stage = "1.6.0 beta 1" +state = "actual" +date = 2000-08-03 + +[[release."1.6"]] +stage = "1.6.0 final" +state = "actual" +date = 2000-09-05 + +[[release."1.6"]] +stage = "1.6.1 final" +state = "actual" +date = 2000-09-05 + +# -- Python 2.0 -------------------------------------------------------------- + +[metadata."2.0"] +pep = 200 +status = "end-of-life" +branch = "2.0" +release-manager = "Jeremy Hylton" +start-of-development = 2000-06-29 +first-release = 2000-10-16 +feature-freeze = 2000-08-14 +end-of-bugfix = 2001-06-22 +end-of-life = 2001-06-22 + +[[release."2.0"]] +stage = "2.0.0 beta 1" +state = "actual" +date = 2000-09-05 + +[[release."2.0"]] +stage = "2.0.0 beta 2" +state = "actual" +date = 2000-09-26 + +[[release."2.0"]] +stage = "2.0.0 candidate 1" +state = "actual" +date = 2000-10-09 + +[[release."2.0"]] +stage = "2.0.0 final" +state = "actual" +date = 2000-10-16 + +# 2.0.1 is not in the PEP, but is found on the website at: +# https://www.python.org/downloads/release/python-201/ +# https://www.python.org/ftp/python/2.0.1/ + +[[release."2.0"]] +stage = "2.0.1 candidate 1" +state = "actual" +date = 2001-06-13 + +[[release."2.0"]] +stage = "2.0.1 final" +state = "actual" +date = 2001-06-22 + +# -- Python 2.1 -------------------------------------------------------------- + +[metadata."2.1"] +pep = 226 +status = "end-of-life" +branch = "2.1" +release-manager = "Jeremy Hylton" +start-of-development = 2000-10-16 +first-release = 2001-04-17 +feature-freeze = 2001-03-02 +end-of-bugfix = 2002-04-09 +end-of-life = 2002-04-09 + +[[release."2.1"]] +stage = "2.1.0 alpha 1" +state = "actual" +date = 2001-01-22 + +[[release."2.1"]] +stage = "2.1.0 alpha 2" +state = "actual" +date = 2001-02-02 + +[[release."2.1"]] +stage = "2.1.0 beta 1" +state = "actual" +date = 2001-03-02 + +[[release."2.1"]] +stage = "2.1.0 beta 2" +state = "actual" +date = 2001-03-23 + +[[release."2.1"]] +stage = "2.1.0 candidate 1" +state = "actual" +date = 2001-04-13 + +[[release."2.1"]] +stage = "2.1.0 candidate 2" +state = "actual" +date = 2001-04-15 + +[[release."2.1"]] +stage = "2.1.0 final" +state = "actual" +date = 2001-04-17 + +# 2.1.{1,2,3} are not in the PEP, but are found on the website at: +# https://www.python.org/downloads/release/python-213/ +# https://www.python.org/ftp/python/2.1.1/ +# https://www.python.org/ftp/python/2.1.2/ +# https://www.python.org/ftp/python/2.1.3/ + +[[release."2.1"]] +stage = "2.1.1 candidate 1" +state = "actual" +date = 2002-07-13 + +[[release."2.1"]] +stage = "2.1.1 final" +state = "actual" +date = 2002-07-20 + +[[release."2.1"]] +stage = "2.1.2 candidate 1" +state = "actual" +date = 2002-01-10 + +[[release."2.1"]] +stage = "2.1.2 final" +state = "actual" +date = 2002-01-15 + +[[release."2.1"]] +stage = "2.1.3 final" +state = "actual" +date = 2002-04-09 + +# -- Python 2.2 -------------------------------------------------------------- + +[metadata."2.2"] +pep = 251 +status = "end-of-life" +branch = "2.2" +release-manager = "Barry Warsaw" +start-of-development = 2001-04-18 +first-release = 2001-12-21 +feature-freeze = 2001-10-19 +end-of-bugfix = 2003-05-30 +end-of-life = 2003-05-30 + +[[release."2.2"]] +stage = "2.2.0 alpha 1" +state = "actual" +date = 2001-07-18 + +[[release."2.2"]] +stage = "2.2.0 alpha 2" +state = "actual" +date = 2001-08-22 + +[[release."2.2"]] +stage = "2.2.0 alpha 3" +state = "actual" +date = 2001-09-07 + +[[release."2.2"]] +stage = "2.2.0 alpha 4" +state = "actual" +date = 2001-09-28 + +[[release."2.2"]] +stage = "2.2.0 beta 1" +state = "actual" +date = 2001-10-19 + +[[release."2.2"]] +stage = "2.2.0 beta 2" +state = "actual" +date = 2001-11-14 + +[[release."2.2"]] +stage = "2.2.0 candidate 1" +state = "actual" +date = 2001-12-14 + +[[release."2.2"]] +stage = "2.2.0 final" +state = "actual" +date = 2001-12-21 + +# 2.2.{1,2,3} are not in the PEP, but are found on the website at: +# https://www.python.org/downloads/release/python-221/ +# https://www.python.org/downloads/release/python-222/ +# https://www.python.org/downloads/release/python-223/ +# https://www.python.org/ftp/python/2.2.1/ +# https://www.python.org/ftp/python/2.2.2/ +# https://www.python.org/ftp/python/2.2.3/ + +[[release."2.2"]] +stage = "2.2.1 candidate 1" +state = "actual" +date = 2002-03-18 + +[[release."2.2"]] +stage = "2.2.1 candidate 2" +state = "actual" +date = 2002-03-26 + +[[release."2.2"]] +stage = "2.2.1 final" +state = "actual" +date = 2002-04-10 + +[[release."2.2"]] +stage = "2.2.2 beta 1" +state = "actual" +date = 2002-10-07 + +[[release."2.2"]] +stage = "2.2.2 final" +state = "actual" +date = 2002-10-14 + +[[release."2.2"]] +stage = "2.2.3 candidate 1" +state = "actual" +date = 2003-05-22 + +[[release."2.2"]] +stage = "2.2.3 final" +state = "actual" +date = 2003-05-30 + +# -- Python 2.3 -------------------------------------------------------------- + +[metadata."2.3"] +pep = 283 +status = "end-of-life" +branch = "2.3" +release-manager = "Barry Warsaw, Jeremy Hylton, Tim Peters" +start-of-development = 2001-12-21 +first-release = 2003-06-29 +feature-freeze = 2003-04-25 +end-of-bugfix = 2008-03-11 +end-of-life = 2008-03-11 + +[[release."2.3"]] +stage = "2.3.0 alpha 1" +state = "actual" +date = 2002-12-31 + +[[release."2.3"]] +stage = "2.3.0 alpha 2" +state = "actual" +date = 2003-02-19 + +[[release."2.3"]] +stage = "2.3.0 beta 1" +state = "actual" +date = 2003-04-25 + +[[release."2.3"]] +stage = "2.3.0 beta 2" +state = "actual" +date = 2003-06-29 + +[[release."2.3"]] +stage = "2.3.0 candidate 1" +state = "actual" +date = 2003-07-18 + +[[release."2.3"]] +stage = "2.3.0 candidate 2" +state = "actual" +date = 2003-07-24 + +[[release."2.3"]] +stage = "2.3.0 final" +state = "actual" +date = 2003-07-29 + +# 2.3.{1,2,3,4,5,6,7} are not in the PEP, but are found on the website at: +# https://www.python.org/downloads/release/python-231/ +# https://www.python.org/downloads/release/python-232/ +# https://www.python.org/downloads/release/python-233/ +# https://www.python.org/downloads/release/python-234/ +# https://www.python.org/downloads/release/python-235/ +# https://www.python.org/downloads/release/python-236/ +# https://www.python.org/downloads/release/python-237/ +# https://www.python.org/ftp/python/2.3.1/ +# https://www.python.org/ftp/python/2.3.2/ +# https://www.python.org/ftp/python/2.3.3/ +# https://www.python.org/ftp/python/2.3.4/ +# https://www.python.org/ftp/python/2.3.5/ +# https://www.python.org/ftp/python/2.3.6/ +# https://www.python.org/ftp/python/2.3.7/ + +[[release."2.3"]] +stage = "2.3.1 candidate 1" +state = "actual" +date = 2003-09-23 + +[[release."2.3"]] +stage = "2.3.1 final" +state = "actual" +date = 2003-09-23 + +[[release."2.3"]] +stage = "2.3.2 candidate 1" +state = "actual" +date = 2003-09-30 + +[[release."2.3"]] +stage = "2.3.2 final" +state = "actual" +date = 2003-10-03 + +[[release."2.3"]] +stage = "2.3.3 candidate 1" +state = "actual" +date = 2003-12-05 + +[[release."2.3"]] +stage = "2.3.3 final" +state = "actual" +date = 2003-12-19 + +[[release."2.3"]] +stage = "2.3.4 candidate 1" +state = "actual" +date = 2004-05-13 + +[[release."2.3"]] +stage = "2.3.4 final" +state = "actual" +date = 2004-05-27 + +[[release."2.3"]] +stage = "2.3.5 candidate 1" +state = "actual" +date = 2004-01-26 + +[[release."2.3"]] +stage = "2.3.5 final" +state = "actual" +date = 2004-02-08 + +[[release."2.3"]] +stage = "2.3.6 candidate 1" +state = "actual" +date = 2006-10-23 + +[[release."2.3"]] +stage = "2.3.6 final" +state = "actual" +date = 2006-11-01 + +[[release."2.3"]] +stage = "2.3.7 candidate 1" +state = "actual" +date = 2008-03-02 + +[[release."2.3"]] +stage = "2.3.7 final" +state = "actual" +date = 2008-03-11 + +# -- Python 2.4 -------------------------------------------------------------- + +[metadata."2.4"] +pep = 320 +status = "end-of-life" +branch = "2.4" +release-manager = "Anthony Baxter" +start-of-development = 2003-07-30 +first-release = 2004-11-30 +feature-freeze = 2004-10-15 +end-of-bugfix = 2008-12-19 +end-of-life = 2008-12-19 + +[[release."2.4"]] +stage = "2.4.0 alpha 1" +state = "actual" +date = 2004-07-09 + +[[release."2.4"]] +stage = "2.4.0 alpha 2" +state = "actual" +date = 2004-08-05 + +[[release."2.4"]] +stage = "2.4.0 alpha 3" +state = "actual" +date = 2004-09-03 + +[[release."2.4"]] +stage = "2.4.0 beta 1" +state = "actual" +date = 2004-10-15 + +[[release."2.4"]] +stage = "2.4.0 beta 2" +state = "actual" +date = 2004-11-03 + +[[release."2.4"]] +stage = "2.4.0 candidate 1" +state = "actual" +date = 2004-11-18 + +[[release."2.4"]] +stage = "2.4.0 final" +state = "actual" +date = 2004-11-30 + +# 2.4.{1,2,3,4,5,6} are not in the PEP, but are found on the website at: +# https://www.python.org/downloads/release/python-241/ +# https://www.python.org/downloads/release/python-242/ +# https://www.python.org/downloads/release/python-243/ +# https://www.python.org/downloads/release/python-244/ +# https://www.python.org/downloads/release/python-245/ +# https://www.python.org/downloads/release/python-246/ +# https://www.python.org/ftp/python/2.4.1/ +# https://www.python.org/ftp/python/2.4.2/ +# https://www.python.org/ftp/python/2.4.3/ +# https://www.python.org/ftp/python/2.4.4/ +# https://www.python.org/ftp/python/2.4.5/ +# https://www.python.org/ftp/python/2.4.6/ + +[[release."2.4"]] +stage = "2.4.1 candidate 1" +state = "actual" +date = 2005-03-10 + +[[release."2.4"]] +stage = "2.4.1 candidate 2" +state = "actual" +date = 2005-03-17 + +[[release."2.4"]] +stage = "2.4.1 final" +state = "actual" +date = 2005-03-30 + +[[release."2.4"]] +stage = "2.4.2 candidate 1" +state = "actual" +date = 2005-09-20 + +[[release."2.4"]] +stage = "2.4.2 final" +state = "actual" +date = 2005-09-27 + +[[release."2.4"]] +stage = "2.4.3 candidate 1" +state = "actual" +date = 2006-03-23 + +[[release."2.4"]] +stage = "2.4.3 final" +state = "actual" +date = 2006-04-15 + +[[release."2.4"]] +stage = "2.4.4 candidate 1" +state = "actual" +date = 2006-10-11 + +[[release."2.4"]] +stage = "2.4.4 final" +state = "actual" +date = 2006-10-18 + +[[release."2.4"]] +stage = "2.4.5 candidate 1" +state = "actual" +date = 2008-03-02 + +[[release."2.4"]] +stage = "2.4.5 final" +state = "actual" +date = 2008-03-11 + +[[release."2.4"]] +stage = "2.4.6 candidate 1" +state = "actual" +date = 2008-12-13 + +[[release."2.4"]] +stage = "2.4.6 final" +state = "actual" +date = 2008-12-19 + +# -- Python 2.5 -------------------------------------------------------------- + +[metadata."2.5"] +pep = 356 +status = "end-of-life" +branch = "2.5" +release-manager = "Anthony Baxter" +start-of-development = 2004-11-30 +first-release = 2006-09-19 +feature-freeze = 2006-06-20 +end-of-bugfix = 2011-05-26 +end-of-life = 2011-05-26 + +[[release."2.5"]] +stage = "2.5.0 alpha 1" +state = "actual" +date = 2006-04-05 + +[[release."2.5"]] +stage = "2.5.0 alpha 2" +state = "actual" +date = 2006-04-27 + +[[release."2.5"]] +stage = "2.5.0 beta 1" +state = "actual" +date = 2006-06-20 + +[[release."2.5"]] +stage = "2.5.0 beta 2" +state = "actual" +date = 2006-07-11 + +[[release."2.5"]] +stage = "2.5.0 beta 3" +state = "actual" +date = 2006-08-03 + +[[release."2.5"]] +stage = "2.5.0 candidate 1" +state = "actual" +date = 2006-08-17 + +[[release."2.5"]] +stage = "2.5.0 candidate 2" +state = "actual" +date = 2006-09-12 + +[[release."2.5"]] +stage = "2.5.0 final" +state = "actual" +date = 2006-09-19 + +# 2.5.{1,2,3,4,5,6} are not in the PEP, but are found on the website at: +# https://www.python.org/downloads/release/python-251/ +# https://www.python.org/downloads/release/python-252/ +# https://www.python.org/downloads/release/python-253/ +# https://www.python.org/downloads/release/python-254/ +# https://www.python.org/downloads/release/python-255/ +# https://www.python.org/downloads/release/python-256/ +# https://www.python.org/ftp/python/2.5.1/ +# https://www.python.org/ftp/python/2.5.2/ +# https://www.python.org/ftp/python/2.5.3/ +# https://www.python.org/ftp/python/2.5.4/ +# https://www.python.org/ftp/python/2.5.5/ +# https://www.python.org/ftp/python/2.5.6/ + +[[release."2.5"]] +stage = "2.5.1 candidate 1" +state = "actual" +date = 2007-04-10 + +[[release."2.5"]] +stage = "2.5.1 final" +state = "actual" +date = 2007-04-19 + +[[release."2.5"]] +stage = "2.5.2 candidate 1" +state = "actual" +date = 2008-02-14 + +[[release."2.5"]] +stage = "2.5.2 final" +state = "actual" +date = 2008-02-21 + +[[release."2.5"]] +stage = "2.5.3 candidate 1" +state = "actual" +date = 2008-12-13 + +[[release."2.5"]] +stage = "2.5.3 final" +state = "actual" +date = 2008-12-19 + +[[release."2.5"]] +stage = "2.5.4 final" +state = "actual" +date = 2008-12-23 + +[[release."2.5"]] +stage = "2.5.5 candidate 1" +state = "actual" +date = 2010-01-14 + +[[release."2.5"]] +stage = "2.5.5 candidate 2" +state = "actual" +date = 2010-01-24 + +[[release."2.5"]] +stage = "2.5.5 final" +state = "actual" +date = 2010-01-31 + +[[release."2.5"]] +stage = "2.5.6 candidate 1" +state = "actual" +date = 2011-04-17 + +[[release."2.5"]] +stage = "2.5.6 final" +state = "actual" +date = 2011-05-26 + +# -- Python 2.6 -------------------------------------------------------------- + +[metadata."2.6"] +pep = 361 +status = "end-of-life" +branch = "2.6" +release-manager = "Barry Warsaw" +start-of-development = 2006-08-18 +first-release = 2008-10-01 +feature-freeze = 2008-06-18 +end-of-bugfix = 2010-08-24 +end-of-life = 2013-10-29 + +[[release."2.6"]] +stage = "2.6.0 alpha 1" +state = "actual" +date = 2008-02-29 + +[[release."2.6"]] +stage = "2.6.0 alpha 2" +state = "actual" +date = 2008-04-02 + +[[release."2.6"]] +stage = "2.6.0 alpha 3" +state = "actual" +date = 2008-05-08 + +[[release."2.6"]] +stage = "2.6.0 beta 1" +state = "actual" +date = 2008-06-18 + +[[release."2.6"]] +stage = "2.6.0 beta 2" +state = "actual" +date = 2008-07-17 + +[[release."2.6"]] +stage = "2.6.0 beta 3" +state = "actual" +date = 2008-08-20 + +[[release."2.6"]] +stage = "2.6.0 candidate 1" +state = "actual" +date = 2008-09-12 + +[[release."2.6"]] +stage = "2.6.0 candidate 2" +state = "actual" +date = 2008-09-17 + +[[release."2.6"]] +stage = "2.6.0 final" +state = "actual" +date = 2008-10-01 + +[[release."2.6"]] +stage = "2.6.1 final" +state = "actual" +date = 2008-12-04 + +[[release."2.6"]] +stage = "2.6.2 candidate 1" +state = "actual" +date = 2009-04-08 + +[[release."2.6"]] +stage = "2.6.2 final" +state = "actual" +date = 2009-04-14 + +[[release."2.6"]] +stage = "2.6.3 candidate 1" +state = "actual" +date = 2009-09-29 + +[[release."2.6"]] +stage = "2.6.3 final" +state = "actual" +date = 2009-10-02 + +[[release."2.6"]] +stage = "2.6.4 candidate 1" +state = "actual" +date = 2009-10-06 + +[[release."2.6"]] +stage = "2.6.4 candidate 2" +state = "actual" +date = 2009-10-18 + +[[release."2.6"]] +stage = "2.6.4 final" +state = "actual" +date = 2009-10-25 + +[[release."2.6"]] +stage = "2.6.5 candidate 1" +state = "actual" +date = 2010-03-01 + +[[release."2.6"]] +stage = "2.6.5 candidate 2" +state = "actual" +date = 2010-03-10 + +[[release."2.6"]] +stage = "2.6.5 final" +state = "actual" +date = 2010-03-19 + +[[release."2.6"]] +stage = "2.6.6 candidate 1" +state = "actual" +date = 2010-08-03 + +[[release."2.6"]] +stage = "2.6.6 candidate 2" +state = "actual" +date = 2010-08-16 + +[[release."2.6"]] +stage = "2.6.6 final" +state = "actual" +date = 2010-08-24 + +[[release."2.6"]] +stage = "2.6.7 candidate 1" +state = "actual" +date = 2011-05-06 + +[[release."2.6"]] +stage = "2.6.7 candidate 2" +state = "actual" +date = 2011-05-21 + +[[release."2.6"]] +stage = "2.6.7 final" +state = "actual" +date = 2011-06-03 + +[[release."2.6"]] +stage = "2.6.8 candidate 1" +state = "actual" +date = 2012-02-23 + +[[release."2.6"]] +stage = "2.6.8 candidate 2" +state = "actual" +date = 2012-03-17 + +[[release."2.6"]] +stage = "2.6.8 final" +state = "actual" +date = 2012-04-10 + +[[release."2.6"]] +stage = "2.6.9 candidate 1" +state = "actual" +date = 2013-10-01 + +[[release."2.6"]] +stage = "2.6.9 final" +state = "actual" +date = 2013-10-29 + +# -- Python 2.7 -------------------------------------------------------------- + +[metadata."2.7"] +pep = 373 +status = "end-of-life" +branch = "2.7" +release-manager = "Benjamin Peterson" +start-of-development = 2008-10-02 +first-release = 2010-07-03 +feature-freeze = 2010-04-03 +end-of-bugfix = 2020-01-01 +end-of-life = 2020-01-01 + +[[release."2.7"]] +stage = "2.7.0 alpha 1" +state = "actual" +date = 2009-12-05 + +[[release."2.7"]] +stage = "2.7.0 alpha 2" +state = "actual" +date = 2010-01-09 + +[[release."2.7"]] +stage = "2.7.0 alpha 3" +state = "actual" +date = 2010-02-06 + +[[release."2.7"]] +stage = "2.7.0 alpha 4" +state = "actual" +date = 2010-03-06 + +[[release."2.7"]] +stage = "2.7.0 beta 1" +state = "actual" +date = 2010-04-03 + +[[release."2.7"]] +stage = "2.7.0 beta 2" +state = "actual" +date = 2010-05-08 + +[[release."2.7"]] +stage = "2.7.0 candidate 1" +state = "actual" +date = 2010-06-05 + +[[release."2.7"]] +stage = "2.7.0 candidate 2" +state = "actual" +date = 2010-06-19 + +[[release."2.7"]] +stage = "2.7.0 final" +state = "actual" +date = 2010-07-03 + +[[release."2.7"]] +stage = "2.7.1 candidate 1" +state = "actual" +date = 2010-11-13 + +[[release."2.7"]] +stage = "2.7.1 final" +state = "actual" +date = 2010-11-27 + +[[release."2.7"]] +stage = "2.7.2 candidate 1" +state = "actual" +date = 2011-05-29 + +[[release."2.7"]] +stage = "2.7.2 final" +state = "actual" +date = 2011-07-21 + +[[release."2.7"]] +stage = "2.7.3 candidate 1" +state = "actual" +date = 2012-02-23 + +[[release."2.7"]] +stage = "2.7.3 candidate 2" +state = "actual" +date = 2012-03-15 + +[[release."2.7"]] +stage = "2.7.3 final" +state = "actual" +date = 2012-03-09 + +[[release."2.7"]] +stage = "2.7.4 candidate 1" +state = "actual" +date = 2013-03-23 + +[[release."2.7"]] +stage = "2.7.4 final" +state = "actual" +date = 2013-04-06 + +[[release."2.7"]] +stage = "2.7.5 final" +state = "actual" +date = 2013-05-12 + +[[release."2.7"]] +stage = "2.7.6 candidate 1" +state = "actual" +date = 2013-10-26 + +[[release."2.7"]] +stage = "2.7.6 final" +state = "actual" +date = 2013-11-10 + +[[release."2.7"]] +stage = "2.7.7 candidate 1" +state = "actual" +date = 2014-05-17 + +[[release."2.7"]] +stage = "2.7.7 final" +state = "actual" +date = 2014-05-31 + +[[release."2.7"]] +stage = "2.7.8 final" +state = "actual" +date = 2014-06-30 + +[[release."2.7"]] +stage = "2.7.9 candidate 1" +state = "actual" +date = 2014-11-26 + +[[release."2.7"]] +stage = "2.7.9 final" +state = "actual" +date = 2014-12-10 + +[[release."2.7"]] +stage = "2.7.10 candidate 1" +state = "actual" +date = 2015-05-09 + +[[release."2.7"]] +stage = "2.7.10 final" +state = "actual" +date = 2015-05-23 + +[[release."2.7"]] +stage = "2.7.11 candidate 1" +state = "actual" +date = 2015-11-21 + +[[release."2.7"]] +stage = "2.7.11 final" +state = "actual" +date = 2015-12-05 + +[[release."2.7"]] +stage = "2.7.12 final" +state = "actual" +date = 2016-06-25 + +[[release."2.7"]] +stage = "2.7.13 candidate 1" +state = "actual" +date = 2016-12-03 + +[[release."2.7"]] +stage = "2.7.13 final" +state = "actual" +date = 2016-12-17 + +[[release."2.7"]] +stage = "2.7.14 candidate 1" +state = "actual" +date = 2017-08-26 + +[[release."2.7"]] +stage = "2.7.14 final" +state = "actual" +date = 2017-09-16 + +[[release."2.7"]] +stage = "2.7.15 candidate 1" +state = "actual" +date = 2018-04-14 + +[[release."2.7"]] +stage = "2.7.15 final" +state = "actual" +date = 2018-05-01 + +[[release."2.7"]] +stage = "2.7.16 candidate 1" +state = "actual" +date = 2019-02-16 + +[[release."2.7"]] +stage = "2.7.16 final" +state = "actual" +date = 2019-03-02 + +[[release."2.7"]] +stage = "2.7.17 candidate 1" +state = "actual" +date = 2019-10-05 + +[[release."2.7"]] +stage = "2.7.17 final" +state = "actual" +date = 2019-10-19 + +[[release."2.7"]] +stage = "2.7.18 candidate 1" +state = "actual" +date = 2020-04-04 + +[[release."2.7"]] +stage = "2.7.18 final" +state = "actual" +date = 2020-04-20 + +# -- Python 3.0 -------------------------------------------------------------- + +[metadata."3.0"] +pep = 361 +status = "end-of-life" +branch = "3.0" +release-manager = "Barry Warsaw" +start-of-development = 2006-03-14 +first-release = 2008-12-03 +feature-freeze = 2008-06-18 +end-of-bugfix = 2009-06-27 +end-of-life = 2009-06-27 + +[[release."3.0"]] +stage = "3.0.0 alpha 1" +state = "actual" +date = 2007-08-31 + +[[release."3.0"]] +stage = "3.0.0 alpha 2" +state = "actual" +date = 2007-12-06 + +[[release."3.0"]] +stage = "3.0.0 alpha 3" +state = "actual" +date = 2008-02-29 + +[[release."3.0"]] +stage = "3.0.0 alpha 4" +state = "actual" +date = 2008-04-02 + +[[release."3.0"]] +stage = "3.0.0 alpha 5" +state = "actual" +date = 2008-05-08 + +[[release."3.0"]] +stage = "3.0.0 beta 1" +state = "actual" +date = 2008-06-18 + +[[release."3.0"]] +stage = "3.0.0 beta 2" +state = "actual" +date = 2008-07-17 + +[[release."3.0"]] +stage = "3.0.0 beta 3" +state = "actual" +date = 2008-08-20 + +[[release."3.0"]] +stage = "3.0.0 candidate 1" +state = "actual" +date = 2008-09-17 + +[[release."3.0"]] +stage = "3.0.0 candidate 2" +state = "actual" +date = 2008-11-06 + +[[release."3.0"]] +stage = "3.0.0 candidate 3" +state = "actual" +date = 2008-11-21 + +[[release."3.0"]] +stage = "3.0.0 final" +state = "actual" +date = 2008-12-03 + +# 3.0.1 is not in the PEP, but is found on the website at: +# https://www.python.org/downloads/release/python-301/ +# https://www.python.org/ftp/python/3.0.1/ + +[[release."3.0"]] +stage = "3.0.1 final" +state = "actual" +date = 2009-02-13 + +# -- Python 3.1 -------------------------------------------------------------- + +[metadata."3.1"] +pep = 375 +status = "end-of-life" +branch = "3.1" +release-manager = "Benjamin Peterson" +start-of-development = 2008-12-03 +first-release = 2009-06-27 +feature-freeze = 2009-05-06 +end-of-bugfix = 2011-06-11 +end-of-life = 2012-04-09 + +[[release."3.1"]] +stage = "3.1.0 alpha 1" +state = "actual" +date = 2009-03-07 + +[[release."3.1"]] +stage = "3.1.0 alpha 2" +state = "actual" +date = 2009-04-04 + +[[release."3.1"]] +stage = "3.1.0 beta 1" +state = "actual" +date = 2009-05-06 + +[[release."3.1"]] +stage = "3.1.0 candidate 1" +state = "actual" +date = 2009-05-30 + +[[release."3.1"]] +stage = "3.1.0 candidate 2" +state = "actual" +date = 2009-06-13 + +[[release."3.1"]] +stage = "3.1.0 final" +state = "actual" +date = 2009-06-27 + +[[release."3.1"]] +stage = "3.1.1 candidate 1" +state = "actual" +date = 2009-08-13 + +[[release."3.1"]] +stage = "3.1.1 final" +state = "actual" +date = 2009-08-16 + +[[release."3.1"]] +stage = "3.1.2 candidate 1" +state = "actual" +date = 2010-03-06 + +[[release."3.1"]] +stage = "3.1.2 final" +state = "actual" +date = 2010-03-20 + +[[release."3.1"]] +stage = "3.1.3 candidate 1" +state = "actual" +date = 2010-11-13 + +[[release."3.1"]] +stage = "3.1.3 final" +state = "actual" +date = 2010-11-27 + +[[release."3.1"]] +stage = "3.1.4 candidate 1" +state = "actual" +date = 2011-05-29 + +[[release."3.1"]] +stage = "3.1.4 final" +state = "actual" +date = 2011-06-11 + +[[release."3.1"]] +stage = "3.1.5 candidate 1" +state = "actual" +date = 2012-02-23 + +[[release."3.1"]] +stage = "3.1.5 candidate 2" +state = "actual" +date = 2012-03-15 + +# PEP 375 states the date as 2012-04-06, but the website lists 2012-04-09: +# https://www.python.org/downloads/release/python-315/ + +[[release."3.1"]] +stage = "3.1.5 final" +state = "actual" +date = 2012-04-09 + +# -- Python 3.2 -------------------------------------------------------------- + +[metadata."3.2"] +pep = 392 +status = "end-of-life" +branch = "3.2" +release-manager = "Georg Brandl" +start-of-development = 2009-06-27 +first-release = 2011-02-20 +feature-freeze = 2010-12-06 +end-of-bugfix = 2013-05-13 +end-of-life = 2016-02-20 + +[[release."3.2"]] +stage = "3.2.0 alpha 1" +state = "actual" +date = 2010-08-01 + +[[release."3.2"]] +stage = "3.2.0 alpha 2" +state = "actual" +date = 2010-09-06 + +[[release."3.2"]] +stage = "3.2.0 alpha 3" +state = "actual" +date = 2010-10-12 + +[[release."3.2"]] +stage = "3.2.0 alpha 4" +state = "actual" +date = 2010-11-16 + +[[release."3.2"]] +stage = "3.2.0 beta 1" +state = "actual" +date = 2010-12-06 + +[[release."3.2"]] +stage = "3.2.0 beta 2" +state = "actual" +date = 2010-12-20 + +[[release."3.2"]] +stage = "3.2.0 candidate 1" +state = "actual" +date = 2011-01-16 + +[[release."3.2"]] +stage = "3.2.0 candidate 2" +state = "actual" +date = 2011-01-31 + +[[release."3.2"]] +stage = "3.2.0 candidate 3" +state = "actual" +date = 2011-02-14 + +[[release."3.2"]] +stage = "3.2.0 final" +state = "actual" +date = 2011-02-20 + +[[release."3.2"]] +stage = "3.2.1 beta 1" +state = "actual" +date = 2011-05-08 + +[[release."3.2"]] +stage = "3.2.1 candidate 1" +state = "actual" +date = 2011-05-17 + +[[release."3.2"]] +stage = "3.2.1 candidate 2" +state = "actual" +date = 2011-07-03 + +[[release."3.2"]] +stage = "3.2.1 final" +state = "actual" +date = 2011-07-11 + +[[release."3.2"]] +stage = "3.2.2 candidate 1" +state = "actual" +date = 2011-08-14 + +[[release."3.2"]] +stage = "3.2.2 final" +state = "actual" +date = 2011-09-04 + +[[release."3.2"]] +stage = "3.2.3 candidate 1" +state = "actual" +date = 2012-02-25 + +[[release."3.2"]] +stage = "3.2.3 candidate 2" +state = "actual" +date = 2012-03-18 + +[[release."3.2"]] +stage = "3.2.3 final" +state = "actual" +date = 2012-04-11 + +[[release."3.2"]] +stage = "3.2.4 candidate 1" +state = "actual" +date = 2013-03-23 + +[[release."3.2"]] +stage = "3.2.4 final" +state = "actual" +date = 2013-04-06 + +[[release."3.2"]] +stage = "3.2.5 final" +state = "actual" +date = 2013-05-13 + +[[release."3.2"]] +stage = "3.2.6 candidate 1" +state = "actual" +date = 2014-10-04 + +[[release."3.2"]] +stage = "3.2.6 final" +state = "actual" +date = 2014-10-11 + +# -- Python 3.3 -------------------------------------------------------------- + +[metadata."3.3"] +pep = 398 +status = "end-of-life" +branch = "3.3" +release-manager = "Georg Brandl, Ned Deily (3.3.7+)" +start-of-development = 2011-02-20 +first-release = 2012-09-29 +feature-freeze = 2012-06-27 +end-of-bugfix = 2014-03-08 +end-of-life = 2017-09-29 + +[[release."3.3"]] +stage = "3.3.0 alpha 1" +state = "actual" +date = 2012-03-05 + +[[release."3.3"]] +stage = "3.3.0 alpha 2" +state = "actual" +date = 2012-04-02 + +[[release."3.3"]] +stage = "3.3.0 alpha 3" +state = "actual" +date = 2012-05-01 + +[[release."3.3"]] +stage = "3.3.0 alpha 4" +state = "actual" +date = 2012-05-31 + +[[release."3.3"]] +stage = "3.3.0 beta 1" +state = "actual" +date = 2012-06-27 + +[[release."3.3"]] +stage = "3.3.0 beta 2" +state = "actual" +date = 2012-08-12 + +[[release."3.3"]] +stage = "3.3.0 candidate 1" +state = "actual" +date = 2012-08-24 + +[[release."3.3"]] +stage = "3.3.0 candidate 2" +state = "actual" +date = 2012-09-09 + +[[release."3.3"]] +stage = "3.3.0 candidate 3" +state = "actual" +date = 2012-09-24 + +[[release."3.3"]] +stage = "3.3.0 final" +state = "actual" +date = 2012-09-29 + +[[release."3.3"]] +stage = "3.3.1 candidate 1" +state = "actual" +date = 2013-03-23 + +[[release."3.3"]] +stage = "3.3.1 final" +state = "actual" +date = 2013-04-06 + +[[release."3.3"]] +stage = "3.3.2 final" +state = "actual" +date = 2013-05-13 + +[[release."3.3"]] +stage = "3.3.3 candidate 1" +state = "actual" +date = 2013-10-27 + +[[release."3.3"]] +stage = "3.3.3 candidate 2" +state = "actual" +date = 2013-11-09 + +[[release."3.3"]] +stage = "3.3.3 final" +state = "actual" +date = 2013-11-16 + +[[release."3.3"]] +stage = "3.3.4 candidate 1" +state = "actual" +date = 2014-01-26 + +[[release."3.3"]] +stage = "3.3.4 final" +state = "actual" +date = 2014-02-09 + +[[release."3.3"]] +stage = "3.3.5 candidate 1" +state = "actual" +date = 2014-02-22 + +[[release."3.3"]] +stage = "3.3.5 candidate 2" +state = "actual" +date = 2014-03-01 + +[[release."3.3"]] +stage = "3.3.5 final" +state = "actual" +date = 2014-03-08 + +[[release."3.3"]] +stage = "3.3.6 candidate 1" +state = "actual" +date = 2014-10-04 + +[[release."3.3"]] +stage = "3.3.6 final" +state = "actual" +date = 2014-10-11 + +[[release."3.3"]] +stage = "3.3.7 candidate 1" +state = "actual" +date = 2017-09-06 + +[[release."3.3"]] +stage = "3.3.7 final" +state = "actual" +date = 2017-09-19 + +# -- Python 3.4 -------------------------------------------------------------- + +[metadata."3.4"] +pep = 429 +status = "end-of-life" +branch = "3.4" +release-manager = "Larry Hastings" +start-of-development = 2012-09-29 +first-release = 2014-03-16 +feature-freeze = 2013-11-24 +end-of-bugfix = 2017-08-09 +end-of-life = 2019-03-18 + +[[release."3.4"]] +stage = "3.4.0 alpha 1" +state = "actual" +date = 2013-08-03 + +[[release."3.4"]] +stage = "3.4.0 alpha 2" +state = "actual" +date = 2013-09-09 + +[[release."3.4"]] +stage = "3.4.0 alpha 3" +state = "actual" +date = 2013-09-29 + +[[release."3.4"]] +stage = "3.4.0 alpha 4" +state = "actual" +date = 2013-10-20 + +[[release."3.4"]] +stage = "3.4.0 beta 1" +state = "actual" +date = 2013-11-24 + +[[release."3.4"]] +stage = "3.4.0 beta 2" +state = "actual" +date = 2014-01-05 + +[[release."3.4"]] +stage = "3.4.0 beta 3" +state = "actual" +date = 2014-01-26 + +[[release."3.4"]] +stage = "3.4.0 candidate 1" +state = "actual" +date = 2014-02-10 + +[[release."3.4"]] +stage = "3.4.0 candidate 2" +state = "actual" +date = 2014-02-23 + +[[release."3.4"]] +stage = "3.4.0 candidate 3" +state = "actual" +date = 2014-03-09 + +[[release."3.4"]] +stage = "3.4.0 final" +state = "actual" +date = 2014-03-16 + +[[release."3.4"]] +stage = "3.4.1 candidate 1" +state = "actual" +date = 2014-05-05 + +[[release."3.4"]] +stage = "3.4.1 final" +state = "actual" +date = 2014-05-18 + +[[release."3.4"]] +stage = "3.4.2 candidate 1" +state = "actual" +date = 2014-09-22 + +[[release."3.4"]] +stage = "3.4.2 final" +state = "actual" +date = 2014-10-06 + +[[release."3.4"]] +stage = "3.4.3 candidate 1" +state = "actual" +date = 2015-02-08 + +[[release."3.4"]] +stage = "3.4.3 final" +state = "actual" +date = 2015-02-25 + +[[release."3.4"]] +stage = "3.4.4 candidate 1" +state = "actual" +date = 2015-12-06 + +[[release."3.4"]] +stage = "3.4.4 final" +state = "actual" +date = 2015-12-20 + +[[release."3.4"]] +stage = "3.4.5 candidate 1" +state = "actual" +date = 2016-06-12 + +[[release."3.4"]] +stage = "3.4.5 final" +state = "actual" +date = 2016-06-26 + +[[release."3.4"]] +stage = "3.4.6 candidate 1" +state = "actual" +date = 2017-01-02 + +[[release."3.4"]] +stage = "3.4.6 final" +state = "actual" +date = 2017-01-17 + +[[release."3.4"]] +stage = "3.4.7 candidate 1" +state = "actual" +date = 2017-07-25 + +[[release."3.4"]] +stage = "3.4.7 final" +state = "actual" +date = 2017-08-09 + +[[release."3.4"]] +stage = "3.4.8 candidate 1" +state = "actual" +date = 2018-01-23 + +[[release."3.4"]] +stage = "3.4.8 final" +state = "actual" +date = 2018-02-04 + +[[release."3.4"]] +stage = "3.4.9 candidate 1" +state = "actual" +date = 2018-07-19 + +[[release."3.4"]] +stage = "3.4.9 final" +state = "actual" +date = 2018-08-02 + +[[release."3.4"]] +stage = "3.4.10 candidate 1" +state = "actual" +date = 2019-03-04 + +[[release."3.4"]] +stage = "3.4.10 final" +state = "actual" +date = 2019-03-18 + +# -- Python 3.5 -------------------------------------------------------------- + +[metadata."3.5"] +pep = 478 +status = "end-of-life" +branch = "3.5" +release-manager = "Larry Hastings" +start-of-development = 2014-03-17 +first-release = 2015-09-13 +feature-freeze = 2015-05-24 +end-of-bugfix = 2017-08-08 +end-of-life = 2020-09-30 + +[[release."3.5"]] +stage = "3.5.0 alpha 1" +state = "actual" +date = 2015-02-08 + +[[release."3.5"]] +stage = "3.5.0 alpha 2" +state = "actual" +date = 2015-03-09 + +[[release."3.5"]] +stage = "3.5.0 alpha 3" +state = "actual" +date = 2015-03-29 + +[[release."3.5"]] +stage = "3.5.0 alpha 4" +state = "actual" +date = 2015-04-19 + +[[release."3.5"]] +stage = "3.5.0 beta 1" +state = "actual" +date = 2015-05-24 + +[[release."3.5"]] +stage = "3.5.0 beta 2" +state = "actual" +date = 2015-05-31 + +[[release."3.5"]] +stage = "3.5.0 beta 3" +state = "actual" +date = 2015-07-05 + +[[release."3.5"]] +stage = "3.5.0 beta 4" +state = "actual" +date = 2015-07-26 + +[[release."3.5"]] +stage = "3.5.0 candidate 1" +state = "actual" +date = 2015-08-10 + +[[release."3.5"]] +stage = "3.5.0 candidate 2" +state = "actual" +date = 2015-08-25 + +[[release."3.5"]] +stage = "3.5.0 candidate 3" +state = "actual" +date = 2015-09-07 + +[[release."3.5"]] +stage = "3.5.0 final" +state = "actual" +date = 2015-09-13 + +[[release."3.5"]] +stage = "3.5.1 candidate 1" +state = "actual" +date = 2015-11-22 + +[[release."3.5"]] +stage = "3.5.1 final" +state = "actual" +date = 2015-12-06 + +[[release."3.5"]] +stage = "3.5.2 candidate 1" +state = "actual" +date = 2016-06-12 + +[[release."3.5"]] +stage = "3.5.2 final" +state = "actual" +date = 2016-06-26 + +[[release."3.5"]] +stage = "3.5.3 candidate 1" +state = "actual" +date = 2017-01-02 + +[[release."3.5"]] +stage = "3.5.3 final" +state = "actual" +date = 2017-01-17 + +[[release."3.5"]] +stage = "3.5.4 candidate 1" +state = "actual" +date = 2017-07-25 + +[[release."3.5"]] +stage = "3.5.4 final" +state = "actual" +date = 2017-08-08 + +[[release."3.5"]] +stage = "3.5.5 candidate 1" +state = "actual" +date = 2018-01-23 + +[[release."3.5"]] +stage = "3.5.5 final" +state = "actual" +date = 2018-02-04 + +[[release."3.5"]] +stage = "3.5.6 candidate 1" +state = "actual" +date = 2018-07-19 + +[[release."3.5"]] +stage = "3.5.6 final" +state = "actual" +date = 2018-08-02 + +[[release."3.5"]] +stage = "3.5.7 candidate 1" +state = "actual" +date = 2019-03-04 + +[[release."3.5"]] +stage = "3.5.7 final" +state = "actual" +date = 2019-03-18 + +[[release."3.5"]] +stage = "3.5.8 candidate 1" +state = "actual" +date = 2019-09-09 + +[[release."3.5"]] +stage = "3.5.8 candidate 2" +state = "actual" +date = 2019-10-12 + +[[release."3.5"]] +stage = "3.5.8 final" +state = "actual" +date = 2019-10-29 + +[[release."3.5"]] +stage = "3.5.9 final" +state = "actual" +date = 2019-11-01 + +[[release."3.5"]] +stage = "3.5.10 candidate 1" +state = "actual" +date = 2020-08-21 + +[[release."3.5"]] +stage = "3.5.10 final" +state = "actual" +date = 2020-09-05 + +# -- Python 3.6 -------------------------------------------------------------- + +[metadata."3.6"] +pep = 494 +status = "end-of-life" +branch = "3.6" +release-manager = "Ned Deily" +start-of-development = 2015-05-24 +first-release = 2016-12-23 +feature-freeze = 2016-09-12 +end-of-bugfix = 2018-12-24 +end-of-life = 2021-12-23 + +[[release."3.6"]] +stage = "3.6.0 alpha 1" +state = "actual" +date = 2016-05-17 + +[[release."3.6"]] +stage = "3.6.0 alpha 2" +state = "actual" +date = 2016-06-13 + +[[release."3.6"]] +stage = "3.6.0 alpha 3" +state = "actual" +date = 2016-07-11 + +[[release."3.6"]] +stage = "3.6.0 alpha 4" +state = "actual" +date = 2016-08-15 + +[[release."3.6"]] +stage = "3.6.0 beta 1" +state = "actual" +date = 2016-09-12 + +[[release."3.6"]] +stage = "3.6.0 beta 2" +state = "actual" +date = 2016-10-10 + +[[release."3.6"]] +stage = "3.6.0 beta 3" +state = "actual" +date = 2016-10-31 + +[[release."3.6"]] +stage = "3.6.0 beta 4" +state = "actual" +date = 2016-11-21 + +[[release."3.6"]] +stage = "3.6.0 candidate 1" +state = "actual" +date = 2016-12-06 + +[[release."3.6"]] +stage = "3.6.0 candidate 2" +state = "actual" +date = 2016-12-16 + +[[release."3.6"]] +stage = "3.6.0 final" +state = "actual" +date = 2016-12-23 + +[[release."3.6"]] +stage = "3.6.1 candidate 1" +state = "actual" +date = 2017-03-05 + +[[release."3.6"]] +stage = "3.6.1 final" +state = "actual" +date = 2017-03-21 + +[[release."3.6"]] +stage = "3.6.2 candidate 1" +state = "actual" +date = 2017-06-17 + +[[release."3.6"]] +stage = "3.6.2 candidate 2" +state = "actual" +date = 2017-07-07 + +[[release."3.6"]] +stage = "3.6.2 final" +state = "actual" +date = 2017-07-17 + +[[release."3.6"]] +stage = "3.6.3 candidate 1" +state = "actual" +date = 2017-09-19 + +[[release."3.6"]] +stage = "3.6.3 final" +state = "actual" +date = 2017-10-03 + +[[release."3.6"]] +stage = "3.6.4 candidate 1" +state = "actual" +date = 2017-12-05 + +[[release."3.6"]] +stage = "3.6.4 final" +state = "actual" +date = 2017-12-19 + +[[release."3.6"]] +stage = "3.6.5 candidate 1" +state = "actual" +date = 2018-03-13 + +[[release."3.6"]] +stage = "3.6.5 final" +state = "actual" +date = 2018-03-28 + +[[release."3.6"]] +stage = "3.6.6 candidate 1" +state = "actual" +date = 2018-06-12 + +[[release."3.6"]] +stage = "3.6.6 final" +state = "actual" +date = 2018-06-27 + +[[release."3.6"]] +stage = "3.6.7 candidate 1" +state = "actual" +date = 2018-09-26 + +[[release."3.6"]] +stage = "3.6.7 candidate 2" +state = "actual" +date = 2018-10-13 + +[[release."3.6"]] +stage = "3.6.7 final" +state = "actual" +date = 2018-10-20 + +[[release."3.6"]] +stage = "3.6.8 candidate 1" +state = "actual" +date = 2018-12-11 + +[[release."3.6"]] +stage = "3.6.8 final" +state = "actual" +date = 2018-12-24 + +[[release."3.6"]] +stage = "3.6.9 candidate 1" +state = "actual" +date = 2019-06-18 + +[[release."3.6"]] +stage = "3.6.9 final" +state = "actual" +date = 2019-07-02 + +[[release."3.6"]] +stage = "3.6.10 candidate 1" +state = "actual" +date = 2019-12-11 + +[[release."3.6"]] +stage = "3.6.10 final" +state = "actual" +date = 2019-12-18 + +[[release."3.6"]] +stage = "3.6.11 candidate 1" +state = "actual" +date = 2020-06-15 + +[[release."3.6"]] +stage = "3.6.11 final" +state = "actual" +date = 2020-06-27 + +[[release."3.6"]] +stage = "3.6.12 final" +state = "actual" +date = 2020-08-17 + +[[release."3.6"]] +stage = "3.6.13 final" +state = "actual" +date = 2021-02-15 + +[[release."3.6"]] +stage = "3.6.14 final" +state = "actual" +date = 2021-06-28 + +[[release."3.6"]] +stage = "3.6.15 final" +state = "actual" +date = 2021-09-04 + +# -- Python 3.7 -------------------------------------------------------------- + +[metadata."3.7"] +pep = 537 +status = "end-of-life" +branch = "3.7" +release-manager = "Ned Deily" +start-of-development = 2016-09-12 +first-release = 2018-06-27 +feature-freeze = 2018-01-31 +end-of-bugfix = 2020-06-27 +end-of-life = 2023-06-27 + +[[release."3.7"]] +stage = "3.7.0 alpha 1" +state = "actual" +date = 2017-09-19 + +[[release."3.7"]] +stage = "3.7.0 alpha 2" +state = "actual" +date = 2017-10-17 + +[[release."3.7"]] +stage = "3.7.0 alpha 3" +state = "actual" +date = 2017-12-05 + +[[release."3.7"]] +stage = "3.7.0 alpha 4" +state = "actual" +date = 2018-01-09 + +[[release."3.7"]] +stage = "3.7.0 beta 1" +state = "actual" +date = 2018-01-31 + +[[release."3.7"]] +stage = "3.7.0 beta 2" +state = "actual" +date = 2018-02-27 + +[[release."3.7"]] +stage = "3.7.0 beta 3" +state = "actual" +date = 2018-03-29 + +[[release."3.7"]] +stage = "3.7.0 beta 4" +state = "actual" +date = 2018-05-02 + +[[release."3.7"]] +stage = "3.7.0 beta 5" +state = "actual" +date = 2018-05-30 + +[[release."3.7"]] +stage = "3.7.0 candidate 1" +state = "actual" +date = 2018-06-12 + +[[release."3.7"]] +stage = "3.7.0 final" +state = "actual" +date = 2018-06-27 + +[[release."3.7"]] +stage = "3.7.1 candidate 1" +state = "actual" +date = 2018-09-26 + +[[release."3.7"]] +stage = "3.7.1 candidate 2" +state = "actual" +date = 2018-10-13 + +[[release."3.7"]] +stage = "3.7.1 final" +state = "actual" +date = 2018-10-20 + +[[release."3.7"]] +stage = "3.7.2 candidate 1" +state = "actual" +date = 2018-12-11 + +[[release."3.7"]] +stage = "3.7.2 final" +state = "actual" +date = 2018-12-24 + +[[release."3.7"]] +stage = "3.7.3 candidate 1" +state = "actual" +date = 2019-03-12 + +[[release."3.7"]] +stage = "3.7.3 final" +state = "actual" +date = 2019-03-25 + +[[release."3.7"]] +stage = "3.7.4 candidate 1" +state = "actual" +date = 2019-06-18 + +[[release."3.7"]] +stage = "3.7.4 candidate 2" +state = "actual" +date = 2019-07-02 + +[[release."3.7"]] +stage = "3.7.4 final" +state = "actual" +date = 2019-07-08 + +[[release."3.7"]] +stage = "3.7.5 candidate 1" +state = "actual" +date = 2019-10-02 + +[[release."3.7"]] +stage = "3.7.5 final" +state = "actual" +date = 2019-10-15 + +[[release."3.7"]] +stage = "3.7.6 candidate 1" +state = "actual" +date = 2019-12-11 + +[[release."3.7"]] +stage = "3.7.6 final" +state = "actual" +date = 2019-12-18 + +[[release."3.7"]] +stage = "3.7.7 candidate 1" +state = "actual" +date = 2020-03-04 + +[[release."3.7"]] +stage = "3.7.7 final" +state = "actual" +date = 2020-03-10 + +[[release."3.7"]] +stage = "3.7.8 candidate 1" +state = "actual" +date = 2020-06-15 + +[[release."3.7"]] +stage = "3.7.8 final" +state = "actual" +date = 2020-06-27 + +[[release."3.7"]] +stage = "3.7.9 final" +state = "actual" +date = 2020-08-17 + +[[release."3.7"]] +stage = "3.7.10 final" +state = "actual" +date = 2021-02-15 + +[[release."3.7"]] +stage = "3.7.11 final" +state = "actual" +date = 2021-06-28 + +[[release."3.7"]] +stage = "3.7.12 final" +state = "actual" +date = 2021-09-04 + +[[release."3.7"]] +stage = "3.7.13 final" +state = "actual" +date = 2022-03-16 + +[[release."3.7"]] +stage = "3.7.14 final" +state = "actual" +date = 2022-09-06 + +[[release."3.7"]] +stage = "3.7.15 final" +state = "actual" +date = 2022-10-11 + +[[release."3.7"]] +stage = "3.7.16 final" +state = "actual" +date = 2022-12-06 + +[[release."3.7"]] +stage = "3.7.17 final" +state = "actual" +date = 2023-06-06 + +# -- Python 3.8 -------------------------------------------------------------- + +[metadata."3.8"] +pep = 569 +status = "end-of-life" +branch = "3.8" +release-manager = "Łukasz Langa" +start-of-development = 2018-01-29 +first-release = 2019-10-14 +feature-freeze = 2019-06-04 +end-of-bugfix = 2021-05-03 +end-of-life = 2024-10-07 + +[[release."3.8"]] +stage = "3.8.0 alpha 1" +state = "actual" +date = 2019-02-03 + +[[release."3.8"]] +stage = "3.8.0 alpha 2" +state = "actual" +date = 2019-02-25 + +[[release."3.8"]] +stage = "3.8.0 alpha 3" +state = "actual" +date = 2019-03-25 + +[[release."3.8"]] +stage = "3.8.0 alpha 4" +state = "actual" +date = 2019-05-06 + +[[release."3.8"]] +stage = "3.8.0 beta 1" +state = "actual" +date = 2019-06-04 + +[[release."3.8"]] +stage = "3.8.0 beta 2" +state = "actual" +date = 2019-07-04 + +[[release."3.8"]] +stage = "3.8.0 beta 3" +state = "actual" +date = 2019-07-29 + +[[release."3.8"]] +stage = "3.8.0 beta 4" +state = "actual" +date = 2019-08-30 + +[[release."3.8"]] +stage = "3.8.0 candidate 1" +state = "actual" +date = 2019-10-01 + +[[release."3.8"]] +stage = "3.8.0 final" +state = "actual" +date = 2019-10-14 + +[[release."3.8"]] +stage = "3.8.1 candidate 1" +state = "actual" +date = 2019-12-10 + +[[release."3.8"]] +stage = "3.8.1 final" +state = "actual" +date = 2019-12-18 + +[[release."3.8"]] +stage = "3.8.2 candidate 1" +state = "actual" +date = 2020-02-10 + +[[release."3.8"]] +stage = "3.8.2 candidate 2" +state = "actual" +date = 2020-02-17 + +[[release."3.8"]] +stage = "3.8.2 final" +state = "actual" +date = 2020-02-24 + +[[release."3.8"]] +stage = "3.8.3 candidate 1" +state = "actual" +date = 2020-04-29 + +[[release."3.8"]] +stage = "3.8.3 final" +state = "actual" +date = 2020-05-13 + +[[release."3.8"]] +stage = "3.8.4 candidate 1" +state = "actual" +date = 2020-06-30 + +[[release."3.8"]] +stage = "3.8.4 final" +state = "actual" +date = 2020-07-13 + +[[release."3.8"]] +stage = "3.8.5 final" +state = "actual" +date = 2020-07-20 +note = "security hotfix" + +[[release."3.8"]] +stage = "3.8.6 candidate 1" +state = "actual" +date = 2020-09-08 + +[[release."3.8"]] +stage = "3.8.6 final" +state = "actual" +date = 2020-09-24 + +[[release."3.8"]] +stage = "3.8.7 candidate 1" +state = "actual" +date = 2020-12-07 + +[[release."3.8"]] +stage = "3.8.7 final" +state = "actual" +date = 2020-12-21 + +[[release."3.8"]] +stage = "3.8.8 candidate 1" +state = "actual" +date = 2021-02-16 + +[[release."3.8"]] +stage = "3.8.8 final" +state = "actual" +date = 2021-02-19 + +[[release."3.8"]] +stage = "3.8.9 final" +state = "actual" +date = 2021-04-02 +note = "security hotfix" + +[[release."3.8"]] +stage = "3.8.10 final" +state = "actual" +date = 2021-05-03 + +[[release."3.8"]] +stage = "3.8.11 final" +state = "actual" +date = 2021-06-28 + +[[release."3.8"]] +stage = "3.8.12 final" +state = "actual" +date = 2021-08-30 + +[[release."3.8"]] +stage = "3.8.13 final" +state = "actual" +date = 2022-03-16 + +[[release."3.8"]] +stage = "3.8.14 final" +state = "actual" +date = 2022-09-06 + +[[release."3.8"]] +stage = "3.8.15 final" +state = "actual" +date = 2022-10-11 + +[[release."3.8"]] +stage = "3.8.16 final" +state = "actual" +date = 2022-12-06 + +[[release."3.8"]] +stage = "3.8.17 final" +state = "actual" +date = 2023-06-06 + + +[[release."3.8"]] +stage = "3.8.18 final" +state = "actual" +date = 2023-08-24 + +[[release."3.8"]] +stage = "3.8.19 final" +state = "actual" +date = 2024-03-19 + +[[release."3.8"]] +stage = "3.8.20 final" +state = "actual" +date = 2024-09-06 +note = "final security release" + +# -- Python 3.9 -------------------------------------------------------------- + +[metadata."3.9"] +pep = 596 +status = "security" +branch = "3.9" +release-manager = "Łukasz Langa" +start-of-development = 2019-06-04 +first-release = 2020-10-05 +feature-freeze = 2020-05-18 +end-of-bugfix = 2022-05-17 +end-of-life = 2025-10-01 + +[[release."3.9"]] +stage = "3.9.0 alpha 1" +state = "actual" +date = 2019-11-19 + +[[release."3.9"]] +stage = "3.9.0 alpha 2" +state = "actual" +date = 2019-12-18 + +[[release."3.9"]] +stage = "3.9.0 alpha 3" +state = "actual" +date = 2020-01-25 + +[[release."3.9"]] +stage = "3.9.0 alpha 4" +state = "actual" +date = 2020-02-26 + +[[release."3.9"]] +stage = "3.9.0 alpha 5" +state = "actual" +date = 2020-03-23 + +[[release."3.9"]] +stage = "3.9.0 alpha 6" +state = "actual" +date = 2020-04-28 + +[[release."3.9"]] +stage = "3.9.0 beta 1" +state = "actual" +date = 2020-05-18 + +# There was no beta 2, the PEP statest that it was recalled. + +[[release."3.9"]] +stage = "3.9.0 beta 3" +state = "actual" +date = 2020-06-09 +note = "beta 2 was recalled." + +[[release."3.9"]] +stage = "3.9.0 beta 4" +state = "actual" +date = 2020-07-03 + +[[release."3.9"]] +stage = "3.9.0 beta 5" +state = "actual" +date = 2020-07-20 + +[[release."3.9"]] +stage = "3.9.0 candidate 1" +state = "actual" +date = 2020-08-11 + +[[release."3.9"]] +stage = "3.9.0 candidate 2" +state = "actual" +date = 2020-09-17 + +[[release."3.9"]] +stage = "3.9.0 final" +state = "actual" +date = 2020-10-05 + +[[release."3.9"]] +stage = "3.9.1 candidate 1" +state = "actual" +date = 2020-11-24 + +[[release."3.9"]] +stage = "3.9.1 final" +state = "actual" +date = 2020-12-07 + +[[release."3.9"]] +stage = "3.9.2 candidate 1" +state = "actual" +date = 2021-02-16 + +[[release."3.9"]] +stage = "3.9.2 final" +state = "actual" +date = 2021-02-19 + +[[release."3.9"]] +stage = "3.9.3 final" +state = "actual" +date = 2021-04-02 +note = "security hotfix; recalled due to bpo-43710" + +[[release."3.9"]] +stage = "3.9.4 final" +state = "actual" +date = 2021-04-04 +note = "ABI compatibility hotfix" + +[[release."3.9"]] +stage = "3.9.5 final" +state = "actual" +date = 2021-05-03 + +[[release."3.9"]] +stage = "3.9.6 final" +state = "actual" +date = 2021-06-28 + +[[release."3.9"]] +stage = "3.9.7 final" +state = "actual" +date = 2021-08-30 + +[[release."3.9"]] +stage = "3.9.8 final" +state = "actual" +date = 2021-11-05 +note = "recalled due to bpo-45235" + +[[release."3.9"]] +stage = "3.9.9 final" +state = "actual" +date = 2021-11-15 + +[[release."3.9"]] +stage = "3.9.10 final" +state = "actual" +date = 2022-01-14 + +[[release."3.9"]] +stage = "3.9.11 final" +state = "actual" +date = 2022-03-16 + +[[release."3.9"]] +stage = "3.9.12 final" +state = "actual" +date = 2022-03-23 + +[[release."3.9"]] +stage = "3.9.13 final" +state = "actual" +date = 2022-05-17 + +[[release."3.9"]] +stage = "3.9.14 final" +state = "actual" +date = 2022-09-06 + +[[release."3.9"]] +stage = "3.9.15 final" +state = "actual" +date = 2022-10-11 + +[[release."3.9"]] +stage = "3.9.16 final" +state = "actual" +date = 2022-12-06 + +[[release."3.9"]] +stage = "3.9.17 final" +state = "actual" +date = 2023-06-06 + +[[release."3.9"]] +stage = "3.9.18 final" +state = "actual" +date = 2023-08-24 + +[[release."3.9"]] +stage = "3.9.19 final" +state = "actual" +date = 2024-03-19 + +[[release."3.9"]] +stage = "3.9.20 final" +state = "actual" +date = 2024-09-06 + +[[release."3.9"]] +stage = "3.9.21 final" +state = "actual" +date = 2024-12-03 + +# -- Python 3.10 -------------------------------------------------------------- + +[metadata."3.10"] +pep = 619 +status = "security" +branch = "3.10" +release-manager = "Pablo Galindo Salgado" +start-of-development = 2020-05-18 +first-release = 2021-10-04 +feature-freeze = 2021-05-03 +end-of-bugfix = 2023-04-05 +end-of-life = 2026-10-01 + +[[release."3.10"]] +stage = "3.10.0 alpha 1" +state = "actual" +date = 2020-10-05 + +[[release."3.10"]] +stage = "3.10.0 alpha 2" +state = "actual" +date = 2020-11-03 + +[[release."3.10"]] +stage = "3.10.0 alpha 3" +state = "actual" +date = 2020-12-07 + +[[release."3.10"]] +stage = "3.10.0 alpha 4" +state = "actual" +date = 2021-01-04 + +[[release."3.10"]] +stage = "3.10.0 alpha 5" +state = "actual" +date = 2021-02-03 + +[[release."3.10"]] +stage = "3.10.0 alpha 6" +state = "actual" +date = 2021-03-01 + +[[release."3.10"]] +stage = "3.10.0 alpha 7" +state = "actual" +date = 2021-04-06 + +[[release."3.10"]] +stage = "3.10.0 beta 1" +state = "actual" +date = 2021-05-03 + +[[release."3.10"]] +stage = "3.10.0 beta 2" +state = "actual" +date = 2021-05-31 + +[[release."3.10"]] +stage = "3.10.0 beta 3" +state = "actual" +date = 2021-06-17 + +[[release."3.10"]] +stage = "3.10.0 beta 4" +state = "actual" +date = 2021-07-10 + +[[release."3.10"]] +stage = "3.10.0 candidate 1" +state = "actual" +date = 2021-08-03 + +[[release."3.10"]] +stage = "3.10.0 candidate 2" +state = "actual" +date = 2021-09-07 + +[[release."3.10"]] +stage = "3.10.0 final" +state = "actual" +date = 2021-10-04 + +[[release."3.10"]] +stage = "3.10.1 final" +state = "actual" +date = 2021-12-06 + +[[release."3.10"]] +stage = "3.10.2 final" +state = "actual" +date = 2022-01-14 + +[[release."3.10"]] +stage = "3.10.3 final" +state = "actual" +date = 2022-03-16 + +[[release."3.10"]] +stage = "3.10.4 final" +state = "actual" +date = 2022-03-24 + +[[release."3.10"]] +stage = "3.10.5 final" +state = "actual" +date = 2022-06-06 + +[[release."3.10"]] +stage = "3.10.6 final" +state = "actual" +date = 2022-08-02 + +[[release."3.10"]] +stage = "3.10.7 final" +state = "actual" +date = 2022-09-06 + +[[release."3.10"]] +stage = "3.10.8 final" +state = "actual" +date = 2022-10-11 + +[[release."3.10"]] +stage = "3.10.9 final" +state = "actual" +date = 2022-12-06 + +[[release."3.10"]] +stage = "3.10.10 final" +state = "actual" +date = 2023-02-08 + +[[release."3.10"]] +stage = "3.10.11 final" +state = "actual" +date = 2023-04-05 + +[[release."3.10"]] +stage = "3.10.12 final" +state = "actual" +date = 2023-06-06 + +[[release."3.10"]] +stage = "3.10.13 final" +state = "actual" +date = 2023-08-24 + +[[release."3.10"]] +stage = "3.10.14 final" +state = "actual" +date = 2024-03-19 + +[[release."3.10"]] +stage = "3.10.15 final" +state = "actual" +date = 2024-09-07 + +[[release."3.10"]] +stage = "3.10.16 final" +state = "actual" +date = 2024-12-03 + +# -- Python 3.11 -------------------------------------------------------------- + +[metadata."3.11"] +pep = 664 +status = "security" +branch = "3.11" +release-manager = "Pablo Galindo Salgado" +start-of-development = 2021-05-03 +first-release = 2022-10-24 +feature-freeze = 2022-05-08 +end-of-bugfix = 2024-04-24 +end-of-life = 2027-10-01 + +[[release."3.11"]] +stage = "3.11.0 alpha 1" +state = "actual" +date = 2021-10-05 + +[[release."3.11"]] +stage = "3.11.0 alpha 2" +state = "actual" +date = 2021-11-02 + +[[release."3.11"]] +stage = "3.11.0 alpha 3" +state = "actual" +date = 2021-12-08 + +[[release."3.11"]] +stage = "3.11.0 alpha 4" +state = "actual" +date = 2022-01-14 + +[[release."3.11"]] +stage = "3.11.0 alpha 5" +state = "actual" +date = 2022-02-03 + +[[release."3.11"]] +stage = "3.11.0 alpha 6" +state = "actual" +date = 2022-03-07 + +[[release."3.11"]] +stage = "3.11.0 alpha 7" +state = "actual" +date = 2022-04-05 + +[[release."3.11"]] +stage = "3.11.0 beta 1" +state = "actual" +date = 2022-05-08 + +[[release."3.11"]] +stage = "3.11.0 beta 2" +state = "actual" +date = 2022-05-31 + +[[release."3.11"]] +stage = "3.11.0 beta 3" +state = "actual" +date = 2022-06-01 + +[[release."3.11"]] +stage = "3.11.0 beta 4" +state = "actual" +date = 2022-07-11 + +[[release."3.11"]] +stage = "3.11.0 beta 5" +state = "actual" +date = 2022-07-26 + +[[release."3.11"]] +stage = "3.11.0 candidate 1" +state = "actual" +date = 2022-08-08 + +[[release."3.11"]] +stage = "3.11.0 candidate 2" +state = "actual" +date = 2022-09-12 + +[[release."3.11"]] +stage = "3.11.0 final" +state = "actual" +date = 2022-10-24 + +[[release."3.11"]] +stage = "3.11.1 final" +state = "actual" +date = 2022-12-06 + +[[release."3.11"]] +stage = "3.11.2 final" +state = "actual" +date = 2023-02-08 + +[[release."3.11"]] +stage = "3.11.3 final" +state = "actual" +date = 2023-04-05 + +[[release."3.11"]] +stage = "3.11.4 final" +state = "actual" +date = 2023-06-06 + +[[release."3.11"]] +stage = "3.11.5 final" +state = "actual" +date = 2023-08-24 + +[[release."3.11"]] +stage = "3.11.6 final" +state = "actual" +date = 2023-10-02 + +[[release."3.11"]] +stage = "3.11.7 final" +state = "actual" +date = 2023-12-04 + +[[release."3.11"]] +stage = "3.11.8 final" +state = "actual" +date = 2024-02-06 + +[[release."3.11"]] +stage = "3.11.9 final" +state = "actual" +date = 2024-04-02 + +[[release."3.11"]] +stage = "3.11.10 final" +state = "actual" +date = 2024-09-07 + +[[release."3.11"]] +stage = "3.11.11 final" +state = "actual" +date = 2024-12-03 + +# -- Python 3.12 -------------------------------------------------------------- + +[metadata."3.12"] +pep = 693 +status = "bugfix" +branch = "3.12" +release-manager = "Thomas Wouters" +start-of-development = 2022-05-08 +first-release = 2023-10-02 +feature-freeze = 2023-05-22 +end-of-bugfix = 2025-04-08 +end-of-life = 2028-10-01 + +[[release."3.12"]] +stage = "3.12.0 alpha 1" +state = "actual" +date = 2022-10-24 + +[[release."3.12"]] +stage = "3.12.0 alpha 2" +state = "actual" +date = 2022-11-14 + +[[release."3.12"]] +stage = "3.12.0 alpha 3" +state = "actual" +date = 2022-12-06 + +[[release."3.12"]] +stage = "3.12.0 alpha 4" +state = "actual" +date = 2023-01-10 + +[[release."3.12"]] +stage = "3.12.0 alpha 5" +state = "actual" +date = 2023-02-07 + +[[release."3.12"]] +stage = "3.12.0 alpha 6" +state = "actual" +date = 2023-03-07 + +[[release."3.12"]] +stage = "3.12.0 alpha 7" +state = "actual" +date = 2023-04-04 + +[[release."3.12"]] +stage = "3.12.0 beta 1" +state = "actual" +date = 2023-05-22 + +[[release."3.12"]] +stage = "3.12.0 beta 2" +state = "actual" +date = 2023-06-06 + +[[release."3.12"]] +stage = "3.12.0 beta 3" +state = "actual" +date = 2023-06-19 + +[[release."3.12"]] +stage = "3.12.0 beta 4" +state = "actual" +date = 2023-07-11 + +[[release."3.12"]] +stage = "3.12.0 candidate 1" +state = "actual" +date = 2023-08-06 + +[[release."3.12"]] +stage = "3.12.0 candidate 2" +state = "actual" +date = 2023-09-06 + +[[release."3.12"]] +stage = "3.12.0 candidate 3" +state = "actual" +date = 2023-09-19 + +[[release."3.12"]] +stage = "3.12.0 final" +state = "actual" +date = 2023-10-02 + +[[release."3.12"]] +stage = "3.12.1 final" +state = "actual" +date = 2023-12-07 + +[[release."3.12"]] +stage = "3.12.2 final" +state = "actual" +date = 2024-02-06 + +[[release."3.12"]] +stage = "3.12.3 final" +state = "actual" +date = 2024-04-09 + +[[release."3.12"]] +stage = "3.12.4 final" +state = "actual" +date = 2024-06-06 + +[[release."3.12"]] +stage = "3.12.5 final" +state = "actual" +date = 2024-08-06 + +[[release."3.12"]] +stage = "3.12.6 final" +state = "actual" +date = 2024-09-06 + +[[release."3.12"]] +stage = "3.12.7 final" +state = "actual" +date = 2024-10-01 + +[[release."3.12"]] +stage = "3.12.8 final" +state = "actual" +date = 2024-12-03 + +[[release."3.12"]] +stage = "3.12.9 final" +state = "actual" +date = 2025-02-04 + +[[release."3.12"]] +stage = "3.12.10 final" +state = "expected" +date = 2025-04-08 + +# -- Python 3.13 -------------------------------------------------------------- + +[metadata."3.13"] +pep = 719 +status = "bugfix" +branch = "3.13" +release-manager = "Thomas Wouters" +start-of-development = 2023-05-22 +first-release = 2024-10-07 +feature-freeze = 2024-05-08 +end-of-bugfix = 2026-10-07 +end-of-life = 2029-10-01 + +[[release."3.13"]] +stage = "3.13.0 alpha 1" +state = "actual" +date = 2023-10-13 + +[[release."3.13"]] +stage = "3.13.0 alpha 2" +state = "actual" +date = 2023-11-22 + +[[release."3.13"]] +stage = "3.13.0 alpha 3" +state = "actual" +date = 2024-01-17 + +[[release."3.13"]] +stage = "3.13.0 alpha 4" +state = "actual" +date = 2024-02-15 + +[[release."3.13"]] +stage = "3.13.0 alpha 5" +state = "actual" +date = 2024-03-12 + +[[release."3.13"]] +stage = "3.13.0 alpha 6" +state = "actual" +date = 2024-04-09 + +[[release."3.13"]] +stage = "3.13.0 beta 1" +state = "actual" +date = 2024-05-08 + +[[release."3.13"]] +stage = "3.13.0 beta 2" +state = "actual" +date = 2024-06-05 + +[[release."3.13"]] +stage = "3.13.0 beta 3" +state = "actual" +date = 2024-06-27 + +[[release."3.13"]] +stage = "3.13.0 beta 4" +state = "actual" +date = 2024-07-18 + +[[release."3.13"]] +stage = "3.13.0 candidate 1" +state = "actual" +date = 2024-08-01 + +[[release."3.13"]] +stage = "3.13.0 candidate 2" +state = "actual" +date = 2024-09-06 + +[[release."3.13"]] +stage = "3.13.0 candidate 3" +state = "actual" +date = 2024-10-01 + +[[release."3.13"]] +stage = "3.13.0 final" +state = "actual" +date = 2024-10-07 + +[[release."3.13"]] +stage = "3.13.1 final" +state = "actual" +date = 2024-12-03 + +[[release."3.13"]] +stage = "3.13.2 final" +state = "actual" +date = 2025-02-04 + +[[release."3.13"]] +stage = "3.13.3 final" +state = "expected" +date = 2025-04-08 + +[[release."3.13"]] +stage = "3.13.4 final" +state = "expected" +date = 2025-06-03 + +[[release."3.13"]] +stage = "3.13.5 final" +state = "expected" +date = 2025-08-05 + +[[release."3.13"]] +stage = "3.13.6 final" +state = "expected" +date = 2025-10-07 + +[[release."3.13"]] +stage = "3.13.7 final" +state = "expected" +date = 2025-12-02 + +[[release."3.13"]] +stage = "3.13.8 final" +state = "expected" +date = 2026-02-03 + +[[release."3.13"]] +stage = "3.13.9 final" +state = "expected" +date = 2026-04-07 + +[[release."3.13"]] +stage = "3.13.10 final" +state = "expected" +date = 2026-06-09 + +[[release."3.13"]] +stage = "3.13.11 final" +state = "expected" +date = 2026-08-04 + +[[release."3.13"]] +stage = "3.13.12 final" +state = "expected" +date = 2026-10-06 + +# -- Python 3.14 -------------------------------------------------------------- + +[metadata."3.14"] +pep = 745 +status = "feature" +branch = "main" +release-manager = "Hugo van Kemenade" +start-of-development = 2024-05-08 +first-release = 2025-10-07 +feature-freeze = 2025-05-06 +end-of-bugfix = 2027-10-07 +end-of-life = 2030-10-01 + +[[release."3.14"]] +stage = "3.14.0 alpha 1" +state = "actual" +date = 2024-10-15 + +[[release."3.14"]] +stage = "3.14.0 alpha 2" +state = "actual" +date = 2024-11-19 + +[[release."3.14"]] +stage = "3.14.0 alpha 3" +state = "actual" +date = 2024-12-17 + +[[release."3.14"]] +stage = "3.14.0 alpha 4" +state = "actual" +date = 2025-01-14 + +[[release."3.14"]] +stage = "3.14.0 alpha 5" +state = "actual" +date = 2025-02-11 + +[[release."3.14"]] +stage = "3.14.0 alpha 6" +state = "actual" +date = 2025-03-14 + +[[release."3.14"]] +stage = "3.14.0 alpha 7" +state = "expected" +date = 2025-04-08 + +[[release."3.14"]] +stage = "3.14.0 beta 1" +state = "expected" +date = 2025-05-06 + +[[release."3.14"]] +stage = "3.14.0 beta 2" +state = "expected" +date = 2025-05-27 + +[[release."3.14"]] +stage = "3.14.0 beta 3" +state = "expected" +date = 2025-06-17 + +[[release."3.14"]] +stage = "3.14.0 beta 4" +state = "expected" +date = 2025-07-08 + +[[release."3.14"]] +stage = "3.14.0 candidate 1" +state = "expected" +date = 2025-07-22 + +[[release."3.14"]] +stage = "3.14.0 candidate 2" +state = "expected" +date = 2025-08-26 + +[[release."3.14"]] +stage = "3.14.0 final" +state = "expected" +date = 2025-10-07 diff --git a/release_engineering/update_release_schedules.py b/release_engineering/update_release_schedules.py new file mode 100644 index 00000000000..4bdb4b81a46 --- /dev/null +++ b/release_engineering/update_release_schedules.py @@ -0,0 +1,178 @@ +"""Update release schedules in PEPs. + +The ``python-releases.toml`` data is treated as authoritative for the given +versions in ``VERSIONS_TO_REGENERATE``. Each PEP must contain markers for the +start and end of each release schedule (feature, bugfix, and security, as +appropriate). These are: + + .. feature release schedule + .. bugfix release schedule + .. security release schedule + .. end of schedule + +This script will use the dates in the [[release."{version}"]] tables to create +and update the release schedule lists in each PEP. + +Optionally, to add a comment or note to a particular release, use the ``note`` +field, which will append the given text in brackets to the relevant line. + +Usage: + + $ python -m release_engineering update-peps + $ # or + $ make regen-all +""" + +from __future__ import annotations + +import datetime as dt + +from release_engineering import ( + PEP_ROOT, + ReleaseInfo, + VersionMetadata, + load_python_releases, +) + +TYPE_CHECKING = False +if TYPE_CHECKING: + from collections.abc import Iterator + + from release_engineering import ReleaseSchedules, ReleaseState, VersionMetadata + +TODAY = dt.date.today() + +SKIPPED_VERSIONS = frozenset({ + '1.6', + '2.0', + '2.1', + '2.2', + '2.3', + '2.4', + '2.5', + '2.6', + '2.7', + '3.0', + '3.1', + '3.2', + '3.3', + '3.4', + '3.5', + '3.6', + '3.7', +}) + + +def update_peps() -> None: + python_releases = load_python_releases() + for version, metadata in python_releases.metadata.items(): + if version in SKIPPED_VERSIONS: + continue + schedules = create_schedules( + version, + python_releases.releases[version], + metadata.start_of_development, + metadata.end_of_bugfix, + ) + update_pep(metadata, schedules) + + +def create_schedules( + version: str, + releases: list[ReleaseInfo], + start_of_development: dt.date, + bugfix_ends: dt.date, +) -> ReleaseSchedules: + schedules: ReleaseSchedules = { + ('feature', 'actual'): [], + ('feature', 'expected'): [], + ('bugfix', 'actual'): [], + ('bugfix', 'expected'): [], + ('security', 'actual'): [], + } + + # first entry into the dictionary + db_state: ReleaseState = 'actual' if TODAY >= start_of_development else 'expected' + schedules['feature', db_state].append( + ReleaseInfo( + stage=f'{version} development begins', + state=db_state, + date=start_of_development, + ) + ) + + for release_info in releases: + if release_info.stage.startswith(f'{version}.0'): + schedules['feature', release_info.state].append(release_info) + elif release_info.date <= bugfix_ends: + schedules['bugfix', release_info.state].append(release_info) + else: + assert release_info.state == 'actual', release_info + schedules['security', release_info.state].append(release_info) + + return schedules + + +def update_pep(metadata: VersionMetadata, schedules: ReleaseSchedules) -> None: + pep_path = PEP_ROOT.joinpath(f'pep-{metadata.pep:0>4}.rst') + pep_lines = iter(pep_path.read_text(encoding='utf-8').splitlines()) + output_lines: list[str] = [] + schedule_name = '' + for line in pep_lines: + output_lines.append(line) + if line.startswith('.. ') and 'schedule' in line: + schedule_name = line.split()[1] + assert schedule_name in {'feature', 'bugfix', 'security'} + output_lines += generate_schedule_lists( + schedules, + schedule_name=schedule_name, + feature_freeze_date=metadata.feature_freeze, + ) + + # skip source lines until the end of schedule marker + while True: + line = next(pep_lines, None) + if line == '.. end of schedule': + output_lines.append(line) + break + if line is None: + raise ValueError('No end of schedule marker found!') + + if not schedule_name: + raise ValueError('No schedule markers found!') + + with open(pep_path, 'w', encoding='utf-8') as f: + f.write('\n'.join(output_lines)) + f.write('\n') # trailing newline + + +def generate_schedule_lists( + schedules: ReleaseSchedules, + *, + schedule_name: str, + feature_freeze_date: dt.date = dt.date.min, +) -> Iterator[str]: + state: ReleaseState + for state in 'actual', 'expected': + if not schedules.get((schedule_name, state)): + continue + + yield '' + if schedule_name != 'security': + yield f'{state.title()}:' + yield '' + for release_info in schedules[schedule_name, state]: + yield release_info.schedule_bullet + if release_info.note: + yield f' ({release_info.note})' + if release_info.date == feature_freeze_date: + yield ' (No new features beyond this point.)' + + if schedule_name == 'bugfix': + yield ' (final regular bugfix release with binary installers)' + + yield '' + + +if __name__ == '__main__': + update_peps()