1030 lines
53 KiB
HTML
1030 lines
53 KiB
HTML
|
||
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<meta name="color-scheme" content="light dark">
|
||
<title>PEP 2026 – Calendar versioning for Python | peps.python.org</title>
|
||
<link rel="shortcut icon" href="../_static/py.png">
|
||
<link rel="canonical" href="https://peps.python.org/pep-2026/">
|
||
<link rel="stylesheet" href="../_static/style.css" type="text/css">
|
||
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
|
||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
|
||
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
|
||
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
|
||
<meta property="og:title" content='PEP 2026 – Calendar versioning for Python | peps.python.org'>
|
||
<meta property="og:description" content="This PEP proposes updating the versioning scheme for Python to include the calendar year.">
|
||
<meta property="og:type" content="website">
|
||
<meta property="og:url" content="https://peps.python.org/pep-2026/">
|
||
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
|
||
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
|
||
<meta property="og:image:alt" content="Python PEPs">
|
||
<meta property="og:image:width" content="200">
|
||
<meta property="og:image:height" content="200">
|
||
<meta name="description" content="This PEP proposes updating the versioning scheme for Python to include the calendar year.">
|
||
<meta name="theme-color" content="#3776ab">
|
||
</head>
|
||
<body>
|
||
|
||
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
|
||
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
|
||
<title>Following system colour scheme</title>
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<circle cx="12" cy="12" r="9"></circle>
|
||
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
|
||
</svg>
|
||
</symbol>
|
||
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
|
||
<title>Selected dark colour scheme</title>
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
|
||
</svg>
|
||
</symbol>
|
||
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
|
||
<title>Selected light colour scheme</title>
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<circle cx="12" cy="12" r="5"></circle>
|
||
<line x1="12" y1="1" x2="12" y2="3"></line>
|
||
<line x1="12" y1="21" x2="12" y2="23"></line>
|
||
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
||
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
||
<line x1="1" y1="12" x2="3" y2="12"></line>
|
||
<line x1="21" y1="12" x2="23" y2="12"></line>
|
||
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
||
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
||
</svg>
|
||
</symbol>
|
||
</svg>
|
||
<script>
|
||
|
||
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
|
||
</script>
|
||
<section id="pep-page-section">
|
||
<header>
|
||
<h1>Python Enhancement Proposals</h1>
|
||
<ul class="breadcrumbs">
|
||
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> » </li>
|
||
<li><a href="../pep-0000/">PEP Index</a> » </li>
|
||
<li>PEP 2026</li>
|
||
</ul>
|
||
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
|
||
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
|
||
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
|
||
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
|
||
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
|
||
</button>
|
||
</header>
|
||
<article>
|
||
<section id="pep-content">
|
||
<h1 class="page-title">PEP 2026 – Calendar versioning for Python</h1>
|
||
<dl class="rfc2822 field-list simple">
|
||
<dt class="field-odd">Author<span class="colon">:</span></dt>
|
||
<dd class="field-odd">Hugo van Kemenade</dd>
|
||
<dt class="field-even">Discussions-To<span class="colon">:</span></dt>
|
||
<dd class="field-even"><a class="reference external" href="https://discuss.python.org/t/pep-2026-calendar-versioning-for-python/55782">Discourse thread</a></dd>
|
||
<dt class="field-odd">Status<span class="colon">:</span></dt>
|
||
<dd class="field-odd"><abbr title="Proposal under active discussion and revision">Draft</abbr></dd>
|
||
<dt class="field-even">Type<span class="colon">:</span></dt>
|
||
<dd class="field-even"><abbr title="Normative PEP describing or proposing a change to a Python community process, workflow or governance">Process</abbr></dd>
|
||
<dt class="field-odd">Created<span class="colon">:</span></dt>
|
||
<dd class="field-odd">11-Jun-2024</dd>
|
||
<dt class="field-even">Python-Version<span class="colon">:</span></dt>
|
||
<dd class="field-even">3.26</dd>
|
||
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
|
||
<dd class="field-odd"><a class="reference external" href="https://discuss.python.org/t/pep-2026-calendar-versioning-for-python/55782" title="Discourse thread">14-Jun-2024</a></dd>
|
||
</dl>
|
||
<hr class="docutils" />
|
||
<section id="contents">
|
||
<details><summary>Table of Contents</summary><ul class="simple">
|
||
<li><a class="reference internal" href="#abstract">Abstract</a></li>
|
||
<li><a class="reference internal" href="#motivation-and-rationale">Motivation and rationale</a><ul>
|
||
<li><a class="reference internal" href="#current-scheme">Current scheme</a></li>
|
||
<li><a class="reference internal" href="#python-predates-semver">Python predates SemVer</a></li>
|
||
<li><a class="reference internal" href="#calendar-versioning">Calendar versioning</a></li>
|
||
<li><a class="reference internal" href="#annual-release-cadence">Annual release cadence</a></li>
|
||
<li><a class="reference internal" href="#calver-for-python">CalVer for Python</a></li>
|
||
<li><a class="reference internal" href="#clarity-of-deprecation-removal">Clarity of deprecation removal</a></li>
|
||
<li><a class="reference internal" href="#clarity-of-support-lifecycle">Clarity of support lifecycle</a></li>
|
||
<li><a class="reference internal" href="#clarity-of-installation-age">Clarity of installation age</a></li>
|
||
<li><a class="reference internal" href="#clarity-of-version-support">Clarity of version support</a></li>
|
||
<li><a class="reference internal" href="#non-goals">Non-goals</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#specification">Specification</a></li>
|
||
<li><a class="reference internal" href="#security-implications">Security implications</a></li>
|
||
<li><a class="reference internal" href="#how-to-teach-this">How to teach this</a></li>
|
||
<li><a class="reference internal" href="#rejected-ideas">Rejected ideas</a><ul>
|
||
<li><a class="reference internal" href="#yy-0">YY.0</a><ul>
|
||
<li><a class="reference internal" href="#platform-compatibility-tags">Platform compatibility tags</a></li>
|
||
<li><a class="reference internal" href="#ecosystem-changes">Ecosystem changes</a></li>
|
||
<li><a class="reference internal" href="#python3-command"><code class="docutils literal notranslate"><span class="pre">python3</span></code> command</a></li>
|
||
<li><a class="reference internal" href="#cpython-changes">CPython changes</a></li>
|
||
<li><a class="reference internal" href="#yy-0-rejection">YY.0 rejection</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#yy-mm">YY.MM</a></li>
|
||
<li><a class="reference internal" href="#yyyy">3.YYYY</a><ul>
|
||
<li><a class="reference internal" href="#py-version-hex"><code class="docutils literal notranslate"><span class="pre">PY_VERSION_HEX</span></code></a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#editions">Editions</a></li>
|
||
<li><a class="reference internal" href="#adopt-semver-and-skip-4">Adopt SemVer and skip 4</a></li>
|
||
<li><a class="reference internal" href="#change-during-3-14-cycle">Change during 3.14 cycle</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#backwards-compatibility">Backwards compatibility</a><ul>
|
||
<li><a class="reference internal" href="#version-mapping">Version mapping</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#forwards-compatibility">Forwards compatibility</a><ul>
|
||
<li><a class="reference internal" href="#future-change-in-cadence">Future change in cadence</a><ul>
|
||
<li><a class="reference internal" href="#less-frequent">Less frequent</a></li>
|
||
<li><a class="reference internal" href="#more-frequent">More frequent</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#no-more-calver">No more CalVer</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#footnotes">Footnotes</a></li>
|
||
<li><a class="reference internal" href="#acknowledgements">Acknowledgements</a></li>
|
||
<li><a class="reference internal" href="#copyright">Copyright</a></li>
|
||
</ul>
|
||
</details></section>
|
||
<section id="abstract">
|
||
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
|
||
<p>This PEP proposes updating the versioning scheme for Python to include
|
||
the calendar year.</p>
|
||
<p>Calendar Versioning (CalVer) makes <em>everything</em> easier to translate into
|
||
calendar time rather than counting versions and looking up when they will be
|
||
(or were) released:</p>
|
||
<ul class="simple">
|
||
<li>The support lifecycle is clear,
|
||
making it easy to see when a version was first released.</li>
|
||
<li>Deprecations are easier to manage for maintainers and users.</li>
|
||
<li>It’s easier to work out when a version will reach end of life (EOL).</li>
|
||
<li>It helps people, especially new learners, understand how old their installation is.</li>
|
||
<li>It’s easier to reason about which versions of Python to support
|
||
for libraries and applications.</li>
|
||
</ul>
|
||
<p>Starting with what would have been Python 3.15,
|
||
the version is 3.YY.micro where YY is the year of initial release:</p>
|
||
<ul class="simple">
|
||
<li>Python 3.26 will be released in 2026 instead of Python 3.15.
|
||
EOL is five years after initial release,
|
||
therefore Python 3.26 will reach EOL in 2031.</li>
|
||
<li>Python 3.27 will be released in 2027, and so on.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="motivation-and-rationale">
|
||
<h2><a class="toc-backref" href="#motivation-and-rationale" role="doc-backlink">Motivation and rationale</a></h2>
|
||
<p>In 2019, we adopted an annual release cycle with <a class="pep reference internal" href="../pep-0602/" title="PEP 602 – Annual Release Cycle for Python">PEP 602</a>, which opened the
|
||
door for calendar versioning:</p>
|
||
<blockquote>
|
||
<div>Adopting an annual release calendar allows for natural switching to calendar
|
||
versioning, for example by calling Python 3.9 “Python 3.20” since it’s
|
||
released in October ‘20 and so on (“Python 3.23” would be the one released
|
||
in October ‘23).<p>While the ease of switching to calendar versioning can be treated as an
|
||
advantage of an annual release cycle, this PEP does not advocate for or
|
||
against a change in how Python is versioned. Should the annual release
|
||
cycle be adopted, the versioning question will be dealt with in a separate
|
||
PEP.</p>
|
||
</div></blockquote>
|
||
<p>This is that PEP.</p>
|
||
<section id="current-scheme">
|
||
<h3><a class="toc-backref" href="#current-scheme" role="doc-backlink">Current scheme</a></h3>
|
||
<p>From the General Python FAQ:
|
||
<a class="reference external" href="https://docs.python.org/3/faq/general.html#faq-version-numbering-scheme" title="(in Python v3.13)"><span>How does the Python version numbering scheme work?</span></a></p>
|
||
<blockquote>
|
||
<div>Python versions are numbered “A.B.C” or “A.B”:<ul class="simple">
|
||
<li><em>A</em> is the major version number
|
||
– it is only incremented for really major changes in the language.</li>
|
||
<li><em>B</em> is the minor version number
|
||
– it is incremented for less earth-shattering changes.</li>
|
||
<li><em>C</em> is the micro version number
|
||
– it is incremented for each bugfix release.</li>
|
||
</ul>
|
||
</div></blockquote>
|
||
</section>
|
||
<section id="python-predates-semver">
|
||
<h3><a class="toc-backref" href="#python-predates-semver" role="doc-backlink">Python predates SemVer</a></h3>
|
||
<p><a class="reference external" href="https://semver.org/">Semantic Versioning</a> (SemVer)
|
||
is a popular scheme which aims to communicate the intent of a release (though it
|
||
<a class="reference external" href="https://hynek.me/articles/semver-will-not-save-you/">doesn’t always succeed</a>).</p>
|
||
<blockquote>
|
||
<div>Given a version number MAJOR.MINOR.PATCH, increment the:<ol class="arabic simple">
|
||
<li>MAJOR version when you make incompatible API changes</li>
|
||
<li>MINOR version when you add functionality in a backward compatible manner</li>
|
||
<li>PATCH version when you make backward compatible bug fixes</li>
|
||
</ol>
|
||
</div></blockquote>
|
||
<p>People often assume Python follows SemVer and
|
||
<a class="reference external" href="https://hugovk.github.io/python-calver/images/images.005.jpg">complain</a>
|
||
<a class="reference external" href="https://web.archive.org/web/20210415230926/https://twitter.com/gjbernat/status/1382833338751328257">about</a>
|
||
<a class="reference external" href="https://web.archive.org/web/20211116214312/https://twitter.com/VictorStinner/status/1460725106129489925">breaking</a>
|
||
<a class="reference external" href="https://web.archive.org/web/20220311211508/https://twitter.com/brettsky/status/1502392549222223872">changes</a>
|
||
in <a class="reference external" href="https://mastodon.social/@hugovk/111974066832803921">feature</a>
|
||
<a class="reference external" href="https://fosstodon.org/@deshipu/112469856667396622">releases</a>.
|
||
But Python predates SemVer by at least 15 years:
|
||
the SemVer spec was <a class="reference external" href="https://github.com/semver/semver.org/commit/ca645805ca206e83c7153c64f9bda54afff06262">introduced in 2009</a>
|
||
and the bespoke Python scheme was <a class="reference external" href="https://github.com/python/cpython/commit/95f61a7ef067dbcabccc9b45ee885b0d55922c5f">added to source control in 1994</a>
|
||
for the 1.0 release.</p>
|
||
<p>If Python adopted SemVer, that would imply a new major bump every year when
|
||
we remove deprecations.</p>
|
||
<p>Instead of SemVer, however, some projects have adopted another versioning
|
||
scheme based on the calendar.</p>
|
||
</section>
|
||
<section id="calendar-versioning">
|
||
<h3><a class="toc-backref" href="#calendar-versioning" role="doc-backlink">Calendar versioning</a></h3>
|
||
<p>With <a class="reference external" href="https://calver.org/">Calendar Versioning</a> (CalVer),
|
||
you include some element of the date in the version number.
|
||
<a class="reference external" href="https://calver.org/users.html">For example</a>,
|
||
Ubuntu and Black use the year and month – Ubuntu 24.04 came out in April 2024;
|
||
pip and PyCharm use only the year.</p>
|
||
<table class="docutils align-default">
|
||
<thead>
|
||
<tr class="row-odd"><th class="head">Ubuntu</th>
|
||
<th class="head">Black</th>
|
||
<th class="head">pip</th>
|
||
<th class="head">PyCharm</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="row-even"><td>YY.0M.micro</td>
|
||
<td>YY.MM.micro</td>
|
||
<td>YY.minor.micro</td>
|
||
<td>YYYY.minor.micro</td>
|
||
</tr>
|
||
<tr class="row-odd"><td><div class="line-block">
|
||
<div class="line">23.04</div>
|
||
<div class="line">23.10</div>
|
||
<div class="line">24.04</div>
|
||
<div class="line">24.10</div>
|
||
</div>
|
||
</td>
|
||
<td><div class="line-block">
|
||
<div class="line">23.12.1</div>
|
||
<div class="line">24.1.0</div>
|
||
<div class="line">24.1.1</div>
|
||
<div class="line">24.2.0</div>
|
||
</div>
|
||
</td>
|
||
<td><div class="line-block">
|
||
<div class="line">23.3</div>
|
||
<div class="line">23.3.1</div>
|
||
<div class="line">23.3.2</div>
|
||
<div class="line">24.0</div>
|
||
</div>
|
||
</td>
|
||
<td><div class="line-block">
|
||
<div class="line">2023.3.5</div>
|
||
<div class="line">2024.1</div>
|
||
<div class="line">2024.1.1</div>
|
||
<div class="line">2024.1.2</div>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>And here are some programming language standards,
|
||
all using some form of the year:</p>
|
||
<table class="docutils align-default">
|
||
<thead>
|
||
<tr class="row-odd"><th class="head">Ada</th>
|
||
<th class="head">Algol</th>
|
||
<th class="head">C</th>
|
||
<th class="head">C++</th>
|
||
<th class="head">Fortran</th>
|
||
<th class="head"><div class="line-block">
|
||
<div class="line">ECMAScript</div>
|
||
<div class="line">aka JavaScript</div>
|
||
</div>
|
||
</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="row-even"><td>YY / YYYY</td>
|
||
<td>YY</td>
|
||
<td>YY</td>
|
||
<td>YY</td>
|
||
<td>YY / YYYY</td>
|
||
<td>YYYY</td>
|
||
</tr>
|
||
<tr class="row-odd"><td><div class="line-block">
|
||
<div class="line">83</div>
|
||
<div class="line">95</div>
|
||
<div class="line">2012</div>
|
||
<div class="line">2022</div>
|
||
</div>
|
||
</td>
|
||
<td><div class="line-block">
|
||
<div class="line">58</div>
|
||
<div class="line">60</div>
|
||
<div class="line">68</div>
|
||
</div>
|
||
</td>
|
||
<td><div class="line-block">
|
||
<div class="line">89</div>
|
||
<div class="line">99</div>
|
||
<div class="line">11</div>
|
||
<div class="line">23</div>
|
||
</div>
|
||
</td>
|
||
<td><div class="line-block">
|
||
<div class="line">98</div>
|
||
<div class="line">03</div>
|
||
<div class="line">11</div>
|
||
<div class="line">23</div>
|
||
</div>
|
||
</td>
|
||
<td><div class="line-block">
|
||
<div class="line">66</div>
|
||
<div class="line">90</div>
|
||
<div class="line">2003</div>
|
||
<div class="line">2023</div>
|
||
</div>
|
||
</td>
|
||
<td><div class="line-block">
|
||
<div class="line">2020</div>
|
||
<div class="line">2021</div>
|
||
<div class="line">2022</div>
|
||
<div class="line">2023</div>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</section>
|
||
<section id="annual-release-cadence">
|
||
<h3><a class="toc-backref" href="#annual-release-cadence" role="doc-backlink">Annual release cadence</a></h3>
|
||
<p>Since 2019, we’ve made a release each year:</p>
|
||
<ul class="simple">
|
||
<li>3.15.0 will be released in 2026</li>
|
||
<li>3.16.0 will be released in 2027</li>
|
||
<li>3.17.0 will be released in 2028</li>
|
||
<li>3.18.0 will be released in 2029</li>
|
||
<li>3.19.0 will be released in 2030</li>
|
||
</ul>
|
||
<p>This is sort of calendar-based, it’s just that it’s offset by 11 years.</p>
|
||
</section>
|
||
<section id="calver-for-python">
|
||
<h3><a class="toc-backref" href="#calver-for-python" role="doc-backlink">CalVer for Python</a></h3>
|
||
<p>The simplest CalVer option would be to stick with major version 3,
|
||
and encode the year in the minor version:</p>
|
||
<ul class="simple">
|
||
<li>3.26.0 will be released in 2026</li>
|
||
<li>3.27.0 will be released in 2027</li>
|
||
<li>3.28.0 will be released in 2028</li>
|
||
<li>3.29.0 will be released in 2029</li>
|
||
<li>3.30.0 will be released in 2030</li>
|
||
</ul>
|
||
<p>For example, 3.26 will be released in 2026.
|
||
It makes it obvious when a release first came out.</p>
|
||
</section>
|
||
<section id="clarity-of-deprecation-removal">
|
||
<h3><a class="toc-backref" href="#clarity-of-deprecation-removal" role="doc-backlink">Clarity of deprecation removal</a></h3>
|
||
<p>Warnings for deprecations often mention the version they will be removed in.
|
||
For example:</p>
|
||
<blockquote>
|
||
<div>DeprecationWarning: ‘ctypes.SetPointerType’ is deprecated and slated for
|
||
removal in Python 3.15</div></blockquote>
|
||
<p>However, once aware of CalVer, it is immediately obvious from the warning how
|
||
long you have to take action:</p>
|
||
<blockquote>
|
||
<div>DeprecationWarning: ‘ctypes.SetPointerType’ is deprecated and slated for
|
||
removal in Python 3.26</div></blockquote>
|
||
</section>
|
||
<section id="clarity-of-support-lifecycle">
|
||
<h3><a class="toc-backref" href="#clarity-of-support-lifecycle" role="doc-backlink">Clarity of support lifecycle</a></h3>
|
||
<p>Right now, it’s a little tricky to work out when a release is end-of-life.
|
||
First you have to look up when it was initially released, then add 5 years:</p>
|
||
<blockquote>
|
||
<div>“When will Python 3.11 be EOL?”<p>“Well, let’s see… PEP 664 is the 3.11 release schedule, it says 3.11 was
|
||
released in 2022, EOL after 5 years, so 2022 + 5 = 2027.”</p>
|
||
</div></blockquote>
|
||
<p>But if the initial release year is right there in the version,
|
||
it’s much easier:</p>
|
||
<blockquote>
|
||
<div>“When will Python 3.26 be EOL?”<p>“26 + 5 = [20]31”</p>
|
||
</div></blockquote>
|
||
</section>
|
||
<section id="clarity-of-installation-age">
|
||
<h3><a class="toc-backref" href="#clarity-of-installation-age" role="doc-backlink">Clarity of installation age</a></h3>
|
||
<p>With the year in the version, it’s easier to work out how old your installation
|
||
is. For example, with the current scheme, if you’re using Python 3.15 in 2035,
|
||
it’s not immediately clear that it was first released in 2026 (and has been EOL
|
||
since 2031).</p>
|
||
<p>With knowledge of CalVer, if you’re using Python 3.26 in 2035, it’s clear it was
|
||
first released nine years ago and it’s probably time to upgrade.</p>
|
||
<p>This can help prompt people to switch to supported releases still under security
|
||
support, and help in teaching new users who may have older installations.</p>
|
||
</section>
|
||
<section id="clarity-of-version-support">
|
||
<h3><a class="toc-backref" href="#clarity-of-version-support" role="doc-backlink">Clarity of version support</a></h3>
|
||
<p>CalVer makes it easier to reason about which versions of Python to support.</p>
|
||
<p>For example, without CalVer, setting your minimum compatible Python version to
|
||
3.19 in 2031 sets an aggressive assumption regarding version adoption and
|
||
support.</p>
|
||
<p>However, with CalVer, this is more obvious if setting the minimum to 3.30 in
|
||
2031. For wider support, perhaps you prefer setting it to 3.26.</p>
|
||
<p>Similarly, library maintainers supporting all CPython upstream versions
|
||
need to test against five versions (or six including the pre-release).</p>
|
||
<p>For example, in 2030, the supported versions without CalVer would be:</p>
|
||
<ul class="simple">
|
||
<li>3.15, 3.16, 3.17, 3.18, 3.19</li>
|
||
</ul>
|
||
<p>With CalVer they would be:</p>
|
||
<ul class="simple">
|
||
<li>3.26, 3.27, 3.28, 3.29, 3.30</li>
|
||
</ul>
|
||
<p>A maintainer can see at a glance which versions are current and need testing.</p>
|
||
</section>
|
||
<section id="non-goals">
|
||
<h3><a class="toc-backref" href="#non-goals" role="doc-backlink">Non-goals</a></h3>
|
||
<p>Like the current scheme, only the micro version will be incremented for bug
|
||
fix and security releases, with no change to the major and minor. For example:</p>
|
||
<table class="docutils align-default">
|
||
<thead>
|
||
<tr class="row-odd"><th class="head"></th>
|
||
<th class="head">Current scheme</th>
|
||
<th class="head">Proposed 3.YY.micro</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="row-even"><td>Initial release (Oct ’26)</td>
|
||
<td>3.15.0</td>
|
||
<td>3.26.0</td>
|
||
</tr>
|
||
<tr class="row-odd"><td>1st bugfix release (Dec ’26)</td>
|
||
<td>3.15.1</td>
|
||
<td>3.26.1</td>
|
||
</tr>
|
||
<tr class="row-even"><td>2nd bugfix release (Feb ’27)</td>
|
||
<td>3.15.2</td>
|
||
<td>3.26.2</td>
|
||
</tr>
|
||
<tr class="row-odd"><td>…</td>
|
||
<td>…</td>
|
||
<td>…</td>
|
||
</tr>
|
||
<tr class="row-even"><td>Final security release (Oct ’31)</td>
|
||
<td>3.15.17</td>
|
||
<td>3.26.17</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>No change to <a class="pep reference internal" href="../pep-0602/" title="PEP 602 – Annual Release Cycle for Python">PEP 602</a> (Annual Release Cycle for Python):</p>
|
||
<ul class="simple">
|
||
<li>No change to the 17 months to develop a feature version: alphas, betas and
|
||
release candidates.</li>
|
||
<li>No change to the support duration:
|
||
two years of full support and three years of security fixes.</li>
|
||
<li>No change to the annual October release cadence.</li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="specification">
|
||
<h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2>
|
||
<p>Python versions are numbered 3.YY.micro where:</p>
|
||
<ul class="simple">
|
||
<li><em>3</em> is the major version number
|
||
– it is always 3.</li>
|
||
<li><em>YY</em> is the minor version number
|
||
- it is the short year number: <code class="docutils literal notranslate"><span class="pre">{year}</span> <span class="pre">-</span> <span class="pre">2000</span></code>.</li>
|
||
<li><em>micro</em> is the micro version number
|
||
- it is incremented for each bugfix or security release.</li>
|
||
</ul>
|
||
<p>We’ll keep major version 3. Python 3 is the brand; there will be no Python 4.</p>
|
||
<p>In the year 2100, the minor will be <code class="docutils literal notranslate"><span class="pre">2100-2000</span> <span class="pre">=</span> <span class="pre">100</span></code>,
|
||
therefore the version will be 3.100.0.</p>
|
||
<p>Python 3.14 will be the last version before this change, released in 2025.
|
||
Python 3.26 will be the first version after this change, released in 2026.
|
||
There will be no Python 3.15 to 3.25 inclusive.</p>
|
||
</section>
|
||
<section id="security-implications">
|
||
<h2><a class="toc-backref" href="#security-implications" role="doc-backlink">Security implications</a></h2>
|
||
<p>None known. No change to durations or timing of bug fix and security phases.</p>
|
||
</section>
|
||
<section id="how-to-teach-this">
|
||
<h2><a class="toc-backref" href="#how-to-teach-this" role="doc-backlink">How to teach this</a></h2>
|
||
<p>We will announce this on blogs, in the 3.14 release notes, documentation,
|
||
and through outreach to the community.</p>
|
||
<p>This change targets the version following 3.14:
|
||
instead of 3.15 it will be 3.26.
|
||
This PEP was proposed in June 2024.
|
||
Development for the 3.15/3.26 release will begin in May 2025,
|
||
with the first alpha in October 2025 and initial release in October 2026.
|
||
We can already update documentation during the 3.14 cycle.
|
||
This gives plenty of notice.</p>
|
||
<p>We can make preview builds which only change the version for early testing.</p>
|
||
<p>We could ship a <code class="docutils literal notranslate"><span class="pre">python3.15</span></code> command as part of Python 3.26 that immediately
|
||
errors out and tells the user to use <code class="docutils literal notranslate"><span class="pre">python3.26</span></code> instead.</p>
|
||
</section>
|
||
<section id="rejected-ideas">
|
||
<span id="pep-2026-rejected"></span><h2><a class="toc-backref" href="#rejected-ideas" role="doc-backlink">Rejected ideas</a></h2>
|
||
<section id="yy-0">
|
||
<span id="pep-2026-yy-0"></span><h3><a class="toc-backref" href="#yy-0" role="doc-backlink">YY.0</a></h3>
|
||
<p>For example, Python 26.0 would be released in 2026.</p>
|
||
<p>There’s <a class="reference external" href="https://www.techrepublic.com/article/programming-languages-why-python-4-0-will-probably-never-arrive-according-to-its-creator/">not much appetite for Python version 4</a>.
|
||
<a class="reference external" href="https://web.archive.org/web/20220906155615/https://twitter.com/gvanrossum/status/1306082472443084801">We don’t want to repeat 2-to-3</a>,
|
||
and 4 has a lot of expectations by now.
|
||
We don’t want “earth-shattering changes”.</p>
|
||
<p>Perhaps Python 4 could be reserved for something big like removing the GIL
|
||
(<a class="pep reference internal" href="../pep-0703/" title="PEP 703 – Making the Global Interpreter Lock Optional in CPython">PEP 703</a>),
|
||
but the Steering Council made it clear the <a class="reference external" href="https://discuss.python.org/t/pep-703-making-the-global-interpreter-lock-optional-in-cpython-acceptance/37075">free-threading rollout must be gradual</a>.
|
||
Will we stick with <a class="reference external" href="https://discuss.python.org/t/python-3-13-alpha-1-contains-breaking-changes-whats-the-plan/37490/11">version 3 forever</a>?</p>
|
||
<p>Another option would be to put the year in the major version and jump to 26.0.
|
||
This could mean we could leapfrog all that 4.0 baggage.</p>
|
||
<section id="platform-compatibility-tags">
|
||
<span id="pep-2026-platform-compatibility-tags"></span><h4><a class="toc-backref" href="#platform-compatibility-tags" role="doc-backlink">Platform compatibility tags</a></h4>
|
||
<p>Changing the major version would complicate packaging, however.</p>
|
||
<p>The <a class="reference external" href="https://packaging.python.org/en/latest/specifications/platform-compatibility-tags/#platform-compatibility-tags" title="(in Python Packaging User Guide)"><span>Platform compatibility tags</span></a> specification says the Python
|
||
version tag used in wheel filenames is given by
|
||
<code class="docutils literal notranslate"><span class="pre">sysconfig.get_config_var("py_version_nodot")</span></code>,
|
||
where the major and minor versions are joined together <em>without a dot</em>.
|
||
For example, 3.9 is <code class="docutils literal notranslate"><span class="pre">39</span></code>.</p>
|
||
<p>During the 3.10 alpha, there was ambiguity because <code class="docutils literal notranslate"><span class="pre">310</span></code> can be interpreted
|
||
as 3.10, 31.0, or 310.</p>
|
||
<p>The specification says an underscore can be used if needed, and <a class="pep reference internal" href="../pep-0641/" title="PEP 641 – Using an underscore in the version portion of Python 3.10 compatibility tags">PEP 641</a>
|
||
(“Using an underscore in the version portion of Python 3.10 compatibility tags”)
|
||
proposed this:</p>
|
||
<table class="docutils align-default">
|
||
<thead>
|
||
<tr class="row-odd"><th class="head"></th>
|
||
<th class="head">Version → tag → version</th>
|
||
<th class="head">PEP 641 proposed version</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="row-even"><td>Pre-3.10</td>
|
||
<td>3.9 → <code class="docutils literal notranslate"><span class="pre">39</span></code></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr class="row-odd"><td>Ambiguity after 3.10</td>
|
||
<td>3.10 → <code class="docutils literal notranslate"><span class="pre">310</span></code> → 3.10 or 31.0 or 310?</td>
|
||
<td><code class="docutils literal notranslate"><span class="pre">3_10</span></code></td>
|
||
</tr>
|
||
<tr class="row-even"><td>Ambiguity with YY.xx</td>
|
||
<td>26.0 → <code class="docutils literal notranslate"><span class="pre">260</span></code> → 2.60 or 26.0 or 260?</td>
|
||
<td><code class="docutils literal notranslate"><span class="pre">26_0</span></code></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>However, PEP 641 was <a class="reference external" href="https://discuss.python.org/t/pep-641-using-an-underscore-in-the-version-portion-of-python-3-10-compatibility-tags/5513/42">rejected</a>
|
||
because it was unknown what side effects there would be on code
|
||
we’re not aware of.</p>
|
||
<p>We would need something like this for YY.0 versioning,
|
||
which would be a significant amount of complex work.</p>
|
||
</section>
|
||
<section id="ecosystem-changes">
|
||
<span id="pep-2026-ecosystem-changes"></span><h4><a class="toc-backref" href="#ecosystem-changes" role="doc-backlink">Ecosystem changes</a></h4>
|
||
<p>Would changing the major version to double digits break code?</p>
|
||
<p>Yes, any novel change to the version inevitably does because people make
|
||
assumptions, such as the major always being 3, or that the version parts are
|
||
always single digits. For example:</p>
|
||
<table class="docutils align-default">
|
||
<thead>
|
||
<tr class="row-odd"><th class="head">Version change</th>
|
||
<th class="head">Example</th>
|
||
<th class="head">Expected</th>
|
||
<th class="head">Actual</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="row-even"><td>2.7.9 → 2.7.10</td>
|
||
<td><div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="s1">'this is Python </span><span class="si">{}</span><span class="s1">'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">version</span><span class="p">[:</span><span class="mi">5</span><span class="p">])</span>
|
||
</pre></div>
|
||
</div>
|
||
</td>
|
||
<td>2.7.10</td>
|
||
<td>2.7.1</td>
|
||
</tr>
|
||
<tr class="row-odd"><td>3.9 → 3.10</td>
|
||
<td><div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="s2">".</span><span class="si">%s</span><span class="s2">-</span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">get_platform</span><span class="p">(),</span> <span class="n">sys</span><span class="o">.</span><span class="n">version</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="mi">3</span><span class="p">])</span>
|
||
</pre></div>
|
||
</div>
|
||
</td>
|
||
<td>3.10</td>
|
||
<td>3.1</td>
|
||
</tr>
|
||
<tr class="row-even"><td>3 → 4</td>
|
||
<td><div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">version_info</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">>=</span> <span class="mi">9</span><span class="p">:</span>
|
||
</pre></div>
|
||
</div>
|
||
</td>
|
||
<td>4.0</td>
|
||
<td>0</td>
|
||
</tr>
|
||
<tr class="row-odd"><td>3 → 26</td>
|
||
<td><div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">version</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'3'</span><span class="p">:</span>
|
||
</pre></div>
|
||
</div>
|
||
</td>
|
||
<td>26</td>
|
||
<td>2</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>The last one here is most relevant for YY.0 versioning.
|
||
Therefore the 3.YY scheme is the safest and requires fewest changes,
|
||
because the <em>shape</em> of the version doesn’t change:
|
||
it’s still a 3 followed by two digits.</p>
|
||
<div class="admonition tip">
|
||
<p class="admonition-title">Tip</p>
|
||
<p>Use
|
||
<a class="reference external" href="https://docs.astral.sh/ruff/rules/#flake8-2020-ytt">Ruff’s YTT rules</a> or
|
||
<a class="reference external" href="https://pypi.org/project/flake8-2020/">Flake8’s flake8-2020 plugin</a>
|
||
to help find the problems like these.</p>
|
||
</div>
|
||
</section>
|
||
<section id="python3-command">
|
||
<span id="pep-2026-python3-command"></span><h4><a class="toc-backref" href="#python3-command" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">python3</span></code> command</a></h4>
|
||
<p><a class="pep reference internal" href="../pep-0394/" title="PEP 394 – The “python” Command on Unix-Like Systems">PEP 394</a> (The “python” Command on Unix-Like Systems)
|
||
outlines recommendations for the <code class="docutils literal notranslate"><span class="pre">python</span></code>, <code class="docutils literal notranslate"><span class="pre">python2</span></code> and <code class="docutils literal notranslate"><span class="pre">python3</span></code>
|
||
commands. <code class="docutils literal notranslate"><span class="pre">python</span></code> can map to either <code class="docutils literal notranslate"><span class="pre">python2</span></code> or <code class="docutils literal notranslate"><span class="pre">python3</span></code>.
|
||
These would need revisiting if the major version changed, and started changing annually.</p>
|
||
<p>Four years after Python 2.7’s end-of-life, we could recommend <code class="docutils literal notranslate"><span class="pre">python</span></code> only
|
||
maps to the latest Python 3+ version.
|
||
But what would <code class="docutils literal notranslate"><span class="pre">python3</span></code> map to when Python 26.0 is out?
|
||
This would introduce additional complexity and cost.</p>
|
||
</section>
|
||
<section id="cpython-changes">
|
||
<h4><a class="toc-backref" href="#cpython-changes" role="doc-backlink">CPython changes</a></h4>
|
||
<p>In addition to <code class="docutils literal notranslate"><span class="pre">python3</span></code> command changes, there are at least four places in
|
||
CPython that assume the major version is 3 and would need updating:</p>
|
||
<ul class="simple">
|
||
<li><a class="reference external" href="https://github.com/python/cpython/blob/406ffb5293a8c9ca315bf63de1ee36a9b33f9aaf/Lib/ast.py#L50-L51">Lib/ast.py</a></li>
|
||
<li><a class="reference external" href="https://github.com/python/cpython/blob/406ffb5293a8c9ca315bf63de1ee36a9b33f9aaf/Parser/pegen.c#L654-L658">Parser/pegen.c</a></li>
|
||
<li><a class="reference external" href="https://github.com/python/cpython/blob/406ffb5293a8c9ca315bf63de1ee36a9b33f9aaf/Parser/pegen.h#L284-L288">Parser/pegen.h</a></li>
|
||
<li><a class="reference external" href="https://github.com/python/cpython/blob/406ffb5293a8c9ca315bf63de1ee36a9b33f9aaf/Parser/string_parser.c#L38-L43">Parser/string_parser.c</a></li>
|
||
</ul>
|
||
</section>
|
||
<section id="yy-0-rejection">
|
||
<h4><a class="toc-backref" href="#yy-0-rejection" role="doc-backlink">YY.0 rejection</a></h4>
|
||
<p>The benefits of calendar versioning are not so big compared to the combined
|
||
costs for YY.0 versioning. Therefore, YY.0 versioning is rejected.</p>
|
||
</section>
|
||
</section>
|
||
<section id="yy-mm">
|
||
<h3><a class="toc-backref" href="#yy-mm" role="doc-backlink">YY.MM</a></h3>
|
||
<p>For example, Python 26.10 would be released in October 2026.</p>
|
||
<p>Building upon YY.0 versioning, we could also include the release month as the minor
|
||
version, like Ubuntu and Black. This would make it clear <em>when</em> in the year it was
|
||
released, and also <em>when</em> in the year it will reach end-of-life.</p>
|
||
<p>However, YY.MM versioning is rejected for many of the same reasons as YY.0 versioning.</p>
|
||
</section>
|
||
<section id="yyyy">
|
||
<h3><a class="toc-backref" href="#yyyy" role="doc-backlink">3.YYYY</a></h3>
|
||
<p>For example, Python 3.2026 would be released in 2026.</p>
|
||
<p>It’s clearer that the minor version is a year when using a four digits, and
|
||
avoids confusion with Ubuntu versions which use YY.MM.</p>
|
||
<section id="py-version-hex">
|
||
<h4><a class="toc-backref" href="#py-version-hex" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">PY_VERSION_HEX</span></code></a></h4>
|
||
<p>CPython’s C API <a class="reference external" href="https://docs.python.org/3/c-api/apiabiversion.html#c.PY_VERSION_HEX" title="(in Python v3.13)"><code class="xref c c-macro docutils literal notranslate"><span class="pre">PY_VERSION_HEX</span></code></a> macro currently uses
|
||
eight bits to encode the minor version, accommodating a maximum minor version of
|
||
255. To hold a four-digit year, it would need to be expanded to 11 bits to fit
|
||
2047 or rather 12 bits for 4095.</p>
|
||
<p>This looks feasible, as it’s intended for numeric comparisons, such as
|
||
<code class="docutils literal notranslate"><span class="pre">#if</span> <span class="pre">PY_VERSION_HEX</span> <span class="pre">>=</span> <span class="pre">...</span></code>. In the <a class="reference external" href="https://dev.to/hugovk/how-to-search-5000-python-projects-31gk">top 8,000 PyPI projects</a>
|
||
only one instance was found of bit shifting
|
||
(<code class="docutils literal notranslate"><span class="pre">hexversion</span> <span class="pre">>></span> <span class="pre">16</span> <span class="pre">!=</span> <span class="pre">PY_VERSION_HEX</span> <span class="pre">>></span> <span class="pre">16</span></code>).</p>
|
||
<p>However, 3.YYYY is rejected as changing from two to four digits would
|
||
nevertheless need more work and break more code than simpler 3.YY versioning.</p>
|
||
</section>
|
||
</section>
|
||
<section id="editions">
|
||
<h3><a class="toc-backref" href="#editions" role="doc-backlink">Editions</a></h3>
|
||
<p>For example, Python 3.15 (2026 Edition) would be released in 2026.</p>
|
||
<p>The Rust language uses
|
||
<a class="reference external" href="https://doc.rust-lang.org/edition-guide/editions/">“Editions”</a>
|
||
to introduce breaking changes. Applying this to Python would require big
|
||
changes to <a class="pep reference internal" href="../pep-0387/" title="PEP 387 – Backwards Compatibility Policy">PEP 387</a> (Backwards Compatibility Policy) and is out of scope
|
||
for this PEP.</p>
|
||
<p>We could apply a year label to releases, such as “Python 3.15 (2026 Edition)”,
|
||
but this is rejected because we’d have to keep track of <em>two</em> numbers.</p>
|
||
</section>
|
||
<section id="adopt-semver-and-skip-4">
|
||
<h3><a class="toc-backref" href="#adopt-semver-and-skip-4" role="doc-backlink">Adopt SemVer and skip 4</a></h3>
|
||
<p>For example, Python 5.0 would be released in 2026, 6.0 in 2027, and so on.</p>
|
||
<p>We could skip the problematic 4.0 entirely and adopt SemVer. Because
|
||
deprecations are removed in every feature release, we would get a new major
|
||
bump every year.</p>
|
||
<p>This is rejected because we wouldn’t get the benefit of calendar versioning, and
|
||
moving away from 3.x would also <a class="reference internal" href="#pep-2026-ecosystem-changes">break code</a>.</p>
|
||
</section>
|
||
<section id="change-during-3-14-cycle">
|
||
<h3><a class="toc-backref" href="#change-during-3-14-cycle" role="doc-backlink">Change during 3.14 cycle</a></h3>
|
||
<p>The Python 3.14 release must go ahead because: π.</p>
|
||
</section>
|
||
</section>
|
||
<section id="backwards-compatibility">
|
||
<h2><a class="toc-backref" href="#backwards-compatibility" role="doc-backlink">Backwards compatibility</a></h2>
|
||
<p>This version change is the safest of the CalVer options considered
|
||
(see <a class="reference internal" href="#pep-2026-rejected">rejected ideas</a>): we keep 3 as the major version,
|
||
and the minor version is still two digits.
|
||
The minor will eventually change to three digits but this is predictable,
|
||
a long way off and can be planned for.</p>
|
||
<p>We retain the <code class="docutils literal notranslate"><span class="pre">python3</span></code> executable.</p>
|
||
<section id="version-mapping">
|
||
<h3><a class="toc-backref" href="#version-mapping" role="doc-backlink">Version mapping</a></h3>
|
||
<p>Versions 3.15 to 3.25 inclusive will be skipped.
|
||
Features, deprecations and removals planned for these will be remapped to the
|
||
new version numbers.</p>
|
||
<p>For example, a deprecation initially planned for removal in 3.16 will instead
|
||
be removed in 3.27.</p>
|
||
<table class="docutils align-default">
|
||
<thead>
|
||
<tr class="row-odd"><th class="head">Old version</th>
|
||
<th class="head">New version</th>
|
||
<th class="head">Initial release</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="row-even"><td>3.14</td>
|
||
<td>3.14 (no change)</td>
|
||
<td>2025</td>
|
||
</tr>
|
||
<tr class="row-odd"><td>3.15</td>
|
||
<td>3.26</td>
|
||
<td>2026</td>
|
||
</tr>
|
||
<tr class="row-even"><td>3.16</td>
|
||
<td>3.27</td>
|
||
<td>2027</td>
|
||
</tr>
|
||
<tr class="row-odd"><td>3.17</td>
|
||
<td>3.28</td>
|
||
<td>2028</td>
|
||
</tr>
|
||
<tr class="row-even"><td>3.18</td>
|
||
<td>3.29</td>
|
||
<td>2029</td>
|
||
</tr>
|
||
<tr class="row-odd"><td>3.19</td>
|
||
<td>3.30</td>
|
||
<td>2030</td>
|
||
</tr>
|
||
<tr class="row-even"><td>3.20</td>
|
||
<td>3.31</td>
|
||
<td>2031</td>
|
||
</tr>
|
||
<tr class="row-odd"><td>3.21</td>
|
||
<td>3.32</td>
|
||
<td>2032</td>
|
||
</tr>
|
||
<tr class="row-even"><td>3.22</td>
|
||
<td>3.33</td>
|
||
<td>2033</td>
|
||
</tr>
|
||
<tr class="row-odd"><td>3.23</td>
|
||
<td>3.34</td>
|
||
<td>2034</td>
|
||
</tr>
|
||
<tr class="row-even"><td>3.24</td>
|
||
<td>3.35</td>
|
||
<td>2035</td>
|
||
</tr>
|
||
<tr class="row-odd"><td>3.25</td>
|
||
<td>3.36</td>
|
||
<td>2036</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</section>
|
||
</section>
|
||
<section id="forwards-compatibility">
|
||
<h2><a class="toc-backref" href="#forwards-compatibility" role="doc-backlink">Forwards compatibility</a></h2>
|
||
<section id="future-change-in-cadence">
|
||
<h3><a class="toc-backref" href="#future-change-in-cadence" role="doc-backlink">Future change in cadence</a></h3>
|
||
<p>This PEP proposes no change to the annual release cadence as defined in
|
||
<a class="pep reference internal" href="../pep-0602/" title="PEP 602 – Annual Release Cycle for Python">PEP 602</a>, which lays out
|
||
<a class="pep reference internal" href="../pep-0602/#rationale-and-goals" title="PEP 602 – Annual Release Cycle for Python § Rationale and Goals">many good reasons for annual releases</a>
|
||
(for example, smaller releases with a predictable release calendar,
|
||
and syncing with external redistributors).
|
||
However unlikely, should we decide to change the cadence in the future, CalVer
|
||
does not preclude doing so.</p>
|
||
<section id="less-frequent">
|
||
<h4><a class="toc-backref" href="#less-frequent" role="doc-backlink">Less frequent</a></h4>
|
||
<p>If we went to <em>fewer than one release per year</em>, the proposed CalVer scheme
|
||
still works; indeed, it even helps people know in which year to expect the
|
||
release. For example, if we released every second year starting in 2036:</p>
|
||
<ul class="simple">
|
||
<li>3.36.0 would be released in 2036</li>
|
||
<li>3.38.0 would be released in 2038</li>
|
||
<li>and so on</li>
|
||
</ul>
|
||
<p>Ecosystem changes depend in part on how the the hypothetical cadence-changing
|
||
PEP updates <a class="pep reference internal" href="../pep-0387/" title="PEP 387 – Backwards Compatibility Policy">PEP 387</a> (Backwards Compatibility Policy). If, for example, it
|
||
requires that the deprecation period must be at least one feature release and
|
||
not the current two (to maintain the minimum two years), CalVer has the benefit
|
||
over the status quo in requiring no changes to planned removal versions
|
||
(other than adjusting any falling in non-release years).</p>
|
||
</section>
|
||
<section id="more-frequent">
|
||
<span id="pep-2026-more-frequent"></span><h4><a class="toc-backref" href="#more-frequent" role="doc-backlink">More frequent</a></h4>
|
||
<p>If we went to <em>more than one release per year</em>, here are some options.
|
||
For example, if we released in April and October starting in 2036, the next
|
||
four releases could be:</p>
|
||
<table class="docutils align-default">
|
||
<thead>
|
||
<tr class="row-odd"><th class="head">Scheme</th>
|
||
<th class="head">Notes</th>
|
||
<th class="head">2036 a</th>
|
||
<th class="head">2036 b</th>
|
||
<th class="head">2037 a</th>
|
||
<th class="head">2037 b</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="row-even"><td>YY.MM.micro</td>
|
||
<td>Year as major, month as minor</td>
|
||
<td>36.04.0</td>
|
||
<td>36.10.0</td>
|
||
<td>37.04.0</td>
|
||
<td>37.10.0</td>
|
||
</tr>
|
||
<tr class="row-odd"><td>YY.x.micro</td>
|
||
<td>Year as major,
|
||
serial number as minor</td>
|
||
<td>36.1.0</td>
|
||
<td>36.2.0</td>
|
||
<td>37.1.0</td>
|
||
<td>37.2.0</td>
|
||
</tr>
|
||
<tr class="row-even"><td>3.YYMM.micro</td>
|
||
<td>Combine year and month
|
||
as minor</td>
|
||
<td>3.3604.0</td>
|
||
<td>3.3610.0</td>
|
||
<td>3.3704.0</td>
|
||
<td>3.3710.0</td>
|
||
</tr>
|
||
<tr class="row-odd"><td>3.YYx.micro</td>
|
||
<td>Combine year and serial number
|
||
as minor</td>
|
||
<td>3.360.0</td>
|
||
<td>3.361.0</td>
|
||
<td>3.370.0</td>
|
||
<td>3.371.0</td>
|
||
</tr>
|
||
<tr class="row-even"><td>3.YY.MM.micro</td>
|
||
<td>Add an extra month segment</td>
|
||
<td>3.36.04.0</td>
|
||
<td>3.36.10.0</td>
|
||
<td>3.37.04.0</td>
|
||
<td>3.37.10.0</td>
|
||
</tr>
|
||
<tr class="row-odd"><td rowspan="3">3.major.micro</td>
|
||
<td rowspan="3">No more CalVer:
|
||
increment minor</td>
|
||
<td>3.36.0</td>
|
||
<td>3.37.0</td>
|
||
<td>3.38.0</td>
|
||
<td>3.39.0</td>
|
||
</tr>
|
||
<tr class="row-even"><td>3.50.0</td>
|
||
<td>3.51.0</td>
|
||
<td>3.52.0</td>
|
||
<td>3.53.0</td>
|
||
</tr>
|
||
<tr class="row-odd"><td>3.100.0</td>
|
||
<td>3.101.0</td>
|
||
<td>3.102.0</td>
|
||
<td>3.103.0</td>
|
||
</tr>
|
||
<tr class="row-even"><td>4.major.micro</td>
|
||
<td rowspan="2">No more CalVer:
|
||
increment major</td>
|
||
<td>4.0.0</td>
|
||
<td>4.1.0</td>
|
||
<td>4.2.0</td>
|
||
<td>4.3.0</td>
|
||
</tr>
|
||
<tr class="row-odd"><td>5.major.micro</td>
|
||
<td>5.0.0</td>
|
||
<td>5.1.0</td>
|
||
<td>5.2.0</td>
|
||
<td>5.3.0</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>The YY options would require addressing issues around the
|
||
<a class="reference internal" href="#pep-2026-platform-compatibility-tags">platform compatibility tags</a>,
|
||
the <a class="reference internal" href="#pep-2026-python3-command">python3 command</a>, and code
|
||
<a class="reference internal" href="#pep-2026-ecosystem-changes">assuming the version always begins with 3</a>.</p>
|
||
<p>The options keeping major version 3 but changing the minor to three or four
|
||
digits would also need to address code
|
||
<a class="reference internal" href="#pep-2026-ecosystem-changes">assuming the version is always two digits</a>.</p>
|
||
<p>The option adding an extra month segment is the biggest change as code would
|
||
need to deal with a four-part version instead of three.</p>
|
||
<p>The options dropping CalVer would be the most conservative
|
||
allowing the major and minor to be chosen freely.</p>
|
||
</section>
|
||
</section>
|
||
<section id="no-more-calver">
|
||
<h3><a class="toc-backref" href="#no-more-calver" role="doc-backlink">No more CalVer</a></h3>
|
||
<p>Adopting CalVer now does not preclude moving away CalVer in the future,
|
||
for example, back to the original scheme, to SemVer or another scheme.
|
||
Some options are <a class="reference internal" href="#pep-2026-more-frequent">listed in the table above</a>.
|
||
If wanting to make it clear the minor is no longer the year,
|
||
it can be bumped to a higher round number (for example, 3.50 or 3.100)
|
||
or the major version can be bumped (for example, to 4.0 or 5.0).
|
||
Additionally, a <a class="reference external" href="https://packaging.python.org/en/latest/specifications/version-specifiers/#version-epochs">version epoch</a>
|
||
could be considered.</p>
|
||
</section>
|
||
</section>
|
||
<section id="footnotes">
|
||
<h2><a class="toc-backref" href="#footnotes" role="doc-backlink">Footnotes</a></h2>
|
||
<p>The author proposed calendar versioning at the <a class="reference external" href="https://us.pycon.org/2024/events/language-summit/">Python Language Summit 2024</a>;
|
||
this PEP is a result of discussions there and during PyCon US.</p>
|
||
<p>Read the <a class="reference external" href="https://hugovk.github.io/python-calver/">slides</a>
|
||
and <a class="reference external" href="https://pyfound.blogspot.com/2024/06/python-language-summit-2024-should-python-adopt-calver.html">blogpost</a>
|
||
of the summit talk.</p>
|
||
</section>
|
||
<section id="acknowledgements">
|
||
<h2><a class="toc-backref" href="#acknowledgements" role="doc-backlink">Acknowledgements</a></h2>
|
||
<p>Thanks to Seth Michael Larson for the Language Summit Q&A notes and blogpost,
|
||
and to everyone who gave feedback at the summit and PyCon US.</p>
|
||
<p>Thank you to Łukasz Langa and Alex Waygood for reviewing a draft of this PEP.</p>
|
||
</section>
|
||
<section id="copyright">
|
||
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
|
||
<p>This document is placed in the public domain or under the
|
||
CC0-1.0-Universal license, whichever is more permissive.</p>
|
||
</section>
|
||
</section>
|
||
<hr class="docutils" />
|
||
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-2026.rst">https://github.com/python/peps/blob/main/peps/pep-2026.rst</a></p>
|
||
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-2026.rst">2024-09-26 00:34:23 GMT</a></p>
|
||
|
||
</article>
|
||
<nav id="pep-sidebar">
|
||
<h2>Contents</h2>
|
||
<ul>
|
||
<li><a class="reference internal" href="#abstract">Abstract</a></li>
|
||
<li><a class="reference internal" href="#motivation-and-rationale">Motivation and rationale</a><ul>
|
||
<li><a class="reference internal" href="#current-scheme">Current scheme</a></li>
|
||
<li><a class="reference internal" href="#python-predates-semver">Python predates SemVer</a></li>
|
||
<li><a class="reference internal" href="#calendar-versioning">Calendar versioning</a></li>
|
||
<li><a class="reference internal" href="#annual-release-cadence">Annual release cadence</a></li>
|
||
<li><a class="reference internal" href="#calver-for-python">CalVer for Python</a></li>
|
||
<li><a class="reference internal" href="#clarity-of-deprecation-removal">Clarity of deprecation removal</a></li>
|
||
<li><a class="reference internal" href="#clarity-of-support-lifecycle">Clarity of support lifecycle</a></li>
|
||
<li><a class="reference internal" href="#clarity-of-installation-age">Clarity of installation age</a></li>
|
||
<li><a class="reference internal" href="#clarity-of-version-support">Clarity of version support</a></li>
|
||
<li><a class="reference internal" href="#non-goals">Non-goals</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#specification">Specification</a></li>
|
||
<li><a class="reference internal" href="#security-implications">Security implications</a></li>
|
||
<li><a class="reference internal" href="#how-to-teach-this">How to teach this</a></li>
|
||
<li><a class="reference internal" href="#rejected-ideas">Rejected ideas</a><ul>
|
||
<li><a class="reference internal" href="#yy-0">YY.0</a><ul>
|
||
<li><a class="reference internal" href="#platform-compatibility-tags">Platform compatibility tags</a></li>
|
||
<li><a class="reference internal" href="#ecosystem-changes">Ecosystem changes</a></li>
|
||
<li><a class="reference internal" href="#python3-command"><code class="docutils literal notranslate"><span class="pre">python3</span></code> command</a></li>
|
||
<li><a class="reference internal" href="#cpython-changes">CPython changes</a></li>
|
||
<li><a class="reference internal" href="#yy-0-rejection">YY.0 rejection</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#yy-mm">YY.MM</a></li>
|
||
<li><a class="reference internal" href="#yyyy">3.YYYY</a><ul>
|
||
<li><a class="reference internal" href="#py-version-hex"><code class="docutils literal notranslate"><span class="pre">PY_VERSION_HEX</span></code></a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#editions">Editions</a></li>
|
||
<li><a class="reference internal" href="#adopt-semver-and-skip-4">Adopt SemVer and skip 4</a></li>
|
||
<li><a class="reference internal" href="#change-during-3-14-cycle">Change during 3.14 cycle</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#backwards-compatibility">Backwards compatibility</a><ul>
|
||
<li><a class="reference internal" href="#version-mapping">Version mapping</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#forwards-compatibility">Forwards compatibility</a><ul>
|
||
<li><a class="reference internal" href="#future-change-in-cadence">Future change in cadence</a><ul>
|
||
<li><a class="reference internal" href="#less-frequent">Less frequent</a></li>
|
||
<li><a class="reference internal" href="#more-frequent">More frequent</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#no-more-calver">No more CalVer</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#footnotes">Footnotes</a></li>
|
||
<li><a class="reference internal" href="#acknowledgements">Acknowledgements</a></li>
|
||
<li><a class="reference internal" href="#copyright">Copyright</a></li>
|
||
</ul>
|
||
|
||
<br>
|
||
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-2026.rst">Page Source (GitHub)</a>
|
||
</nav>
|
||
</section>
|
||
<script src="../_static/colour_scheme.js"></script>
|
||
<script src="../_static/wrap_tables.js"></script>
|
||
<script src="../_static/sticky_banner.js"></script>
|
||
</body>
|
||
</html> |