python-peps/pep-0387/index.html

330 lines
20 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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 387 Backwards Compatibility Policy | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0387/">
<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 387 Backwards Compatibility Policy | peps.python.org'>
<meta property="og:description" content="This PEP outlines Pythons backwards compatibility policy.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0387/">
<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 outlines Pythons backwards compatibility policy.">
<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> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 387</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 387 Backwards Compatibility Policy</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Benjamin Peterson &lt;benjamin&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-even">PEP-Delegate<span class="colon">:</span></dt>
<dd class="field-even">Brett Cannon &lt;brett&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-odd">Status<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Currently valid informational guidance, or an in-use process">Active</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">18-Jun-2009</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even"><a class="reference external" href="https://mail.python.org/archives/list/python-dev&#64;python.org/thread/YAZQHFUCYEYIX5MIG6LFJLCVQ5ORVUM6/" title="Python-Dev thread">19-Jun-2009</a>,
<a class="reference external" href="https://discuss.python.org/t/pep-387-backwards-compatibilty-policy/4421" title="Discourse thread">12-Jun-2020</a>,
<a class="reference external" href="https://discuss.python.org/t/22042" title="Discourse thread">19-Dec-2022</a>,
<a class="reference external" href="https://discuss.python.org/t/formalize-the-concept-of-soft-deprecation-dont-schedule-removal-in-pep-387-backwards-compatibility-policy/27957" title="Discourse thread">16-Jun-2023</a></dd>
<dt class="field-odd">Replaces<span class="colon">:</span></dt>
<dd class="field-odd"><a class="reference external" href="../pep-0291/">291</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="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#backwards-compatibility-rules">Backwards Compatibility Rules</a><ul>
<li><a class="reference internal" href="#basic-policy-for-backwards-compatibility">Basic policy for backwards compatibility</a></li>
</ul>
</li>
<li><a class="reference internal" href="#soft-deprecation">Soft Deprecation</a></li>
<li><a class="reference internal" href="#making-incompatible-changes">Making Incompatible Changes</a></li>
<li><a class="reference internal" href="#changelog">Changelog</a></li>
<li><a class="reference internal" href="#references">References</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 outlines Pythons backwards compatibility policy.</p>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>As one of the most used programming languages today <a class="footnote-reference brackets" href="#tiobe" id="id1">[1]</a>, the
Python core language and its standard library play a critical role in
millions of applications and libraries. This is fantastic. However, it
means the development team must be very careful not to break this
existing 3rd party code with new releases.</p>
<p>This PEP takes the perspective that “backwards incompatibility” means
preexisting code ceases to comparatively function after a change. It is
acknowledged that this is not a concrete definition, but the expectation
is people in general understand what is meant by
“backwards incompatibility”, and if they are unsure they may ask the
Python development team and/or steering council for guidance.</p>
</section>
<section id="backwards-compatibility-rules">
<h2><a class="toc-backref" href="#backwards-compatibility-rules" role="doc-backlink">Backwards Compatibility Rules</a></h2>
<p>This policy applies to all public APIs. These include:</p>
<ul class="simple">
<li>Syntax and behavior of these constructs as defined by the reference
manual.</li>
<li>The C-API.</li>
<li>Function, class, module, attribute, and method names and types.</li>
<li>Given a set of arguments, the return value, side effects, and raised
exceptions of a function. This does not preclude changes from
reasonable bug fixes.</li>
<li>The position and expected types of arguments and returned values.</li>
<li>Behavior of classes with regards to subclasses: the conditions under
which overridden methods are called.</li>
<li>Documented exceptions and the semantics which lead to their raising.</li>
<li>Exceptions commonly raised in EAFP scenarios.</li>
</ul>
<p>Others are explicitly not part of the public API. They can change or
be removed at any time in any way. These include:</p>
<ul class="simple">
<li>Function, class, module, attribute, method, and C-API names and
types that are prefixed by “_” (except special names).</li>
<li>Anything documented publicly as being private.
Note that if something is not documented at all, it is <em>not</em>
automatically considered private.</li>
<li>Imported modules (unless explicitly documented as part of the public
API; e.g. importing the <code class="docutils literal notranslate"><span class="pre">bacon</span></code> module in the <code class="docutils literal notranslate"><span class="pre">spam</span></code> does not
automatically mean <code class="docutils literal notranslate"><span class="pre">spam.bacon</span></code> is part of the public API unless
it is documented as such).</li>
<li>Inheritance patterns of internal classes.</li>
<li>Test suites. (Anything in the <code class="docutils literal notranslate"><span class="pre">Lib/test</span></code> directory or test
subdirectories of packages.)</li>
<li>Backward compatibility rules do not apply to any module or API that is
explicitly documented as <strong>Provisional</strong> per <a class="pep reference internal" href="../pep-0411/" title="PEP 411 Provisional packages in the Python standard library">PEP 411</a>.</li>
</ul>
<section id="basic-policy-for-backwards-compatibility">
<h3><a class="toc-backref" href="#basic-policy-for-backwards-compatibility" role="doc-backlink">Basic policy for backwards compatibility</a></h3>
<ul class="simple">
<li>In general, incompatibilities should have a large benefit to
breakage ratio, and the incompatibility should be easy to resolve in
affected code. For example, adding an stdlib module with the same
name as a third party package is generally not acceptable. Adding
a method or attribute that conflicts with 3rd party code through
inheritance, however, is likely reasonable.</li>
<li>Unless it is going through the deprecation process below, the
behavior of an API <em>must</em> not change in an incompatible fashion
between any two consecutive releases. Pythons yearly release
process (<a class="pep reference internal" href="../pep-0602/" title="PEP 602 Annual Release Cycle for Python">PEP 602</a>) means that the deprecation period must last at
least two years.</li>
<li>Similarly a feature cannot be removed without notice between any two
consecutive releases.</li>
<li>For changes that are unable to raise a deprecation warning, consult
with the steering council.</li>
<li>The steering council may grant exceptions to this policy. In
particular, they may shorten the required deprecation period for a
feature. Exceptions are only granted for extreme situations such as
dangerously broken or insecure features or features no one could
reasonably be depending on (e.g., support for completely obsolete
platforms).</li>
</ul>
</section>
</section>
<section id="soft-deprecation">
<h2><a class="toc-backref" href="#soft-deprecation" role="doc-backlink">Soft Deprecation</a></h2>
<p>A soft deprecation can be used when using an API which should no longer
be used to write new code, but it remains safe to continue using it in
existing code. The API remains documented and tested, but will not be
developed further (no enhancement).</p>
<p>The main difference between a “soft” and a (regular) “hard” deprecation
is that the soft deprecation does not imply scheduling the removal of
the deprecated API.</p>
<p>Another difference is that a soft deprecation does not issue a warning:
its only mentioned in the documentation, whereas usually a “hard”
deprecation issues a <code class="docutils literal notranslate"><span class="pre">DeprecationWarning</span></code> warning at runtime. The
documentation of a soft deprecation should explain why the API should be
avoided, and if possible propose a replacement.</p>
<p>If the decision is made to deprecate (in the regular sense) a feature
that is currently soft deprecated, the deprecation must follow the
<a class="reference internal" href="#backwards-compatibility-rules">Backwards Compatibility Rules</a> (i.e., there is no exception because
the feature is already soft deprecated).</p>
</section>
<section id="making-incompatible-changes">
<h2><a class="toc-backref" href="#making-incompatible-changes" role="doc-backlink">Making Incompatible Changes</a></h2>
<p>Making an incompatible change is a gradual process performed over
several releases:</p>
<ol class="arabic">
<li>Discuss the change. Depending on the degree of incompatibility,
this could be on the bug tracker, python-dev, python-list, or the
appropriate SIG. A PEP or similar document may be written.
Hopefully users of the affected API will pipe up to comment.</li>
<li>Add a warning to the current <code class="docutils literal notranslate"><span class="pre">main</span></code> branch.
If behavior is changing, the API may gain a new
function or method to perform the new behavior; old usage should
raise the warning. If an API is being removed, simply warn
whenever it is entered. <code class="docutils literal notranslate"><span class="pre">DeprecationWarning</span></code> is the usual
warning category to use, but <code class="docutils literal notranslate"><span class="pre">PendingDeprecationWarning</span></code> may be
used in special cases where the old and new versions of the API will
coexist for many releases <a class="footnote-reference brackets" href="#warnings" id="id2">[2]</a>. The warning message should
include the release the incompatibility is expected to become the
default and a link to an issue that users can post feedback to.
When feasible, also change <a class="reference external" href="https://github.com/python/typeshed">typeshed</a>
to add the <code class="docutils literal notranslate"><span class="pre">&#64;deprecated</span></code> decorator (see <a class="pep reference internal" href="../pep-0702/" title="PEP 702 Marking deprecations using the type system">PEP 702</a>) to the deprecated API,
so that users of static type checkers have another way to learn
about the deprecation.<p>For C API, a compiler warning generated by the <code class="docutils literal notranslate"><span class="pre">Py_DEPRECATED</span></code> macro
is also acceptable.</p>
</li>
<li>Wait for the warning to appear in at least two minor Python
versions of the same major version, or one minor version in an older
major version (e.g. for a warning in Python 3.10.0, you either wait
until at least Python 3.12 or Python 4.0 to make the change).<p>Its fine to wait more than two releases, for example:</p>
<ul class="simple">
<li>If the expected maintenance overhead and security risk of the
deprecated behavior is small (e.g. an old function is reimplemented
in terms of a new, more general one), it can stay indefinitely
(or until the situation changes).</li>
<li>If the deprecated feature is replaced by a new one, it should
generally be removed only after the last Python version
<em>without</em> the new feature reaches end of support.</li>
</ul>
</li>
<li>See if theres any feedback. Users not involved in the original
discussions may comment now after seeing the warning. Perhaps
reconsider.</li>
<li>The behavior change or feature removal may now be made default or
permanent having reached the declared version. Remove the old
version and warning.</li>
<li>If a warning cannot be provided to users, consult with the steering
council.</li>
</ol>
</section>
<section id="changelog">
<h2><a class="toc-backref" href="#changelog" role="doc-backlink">Changelog</a></h2>
<ul class="simple">
<li>2023-Nov-14: Added <code class="docutils literal notranslate"><span class="pre">&#64;deprecated</span></code> decorator per <a class="pep reference internal" href="../pep-0702/" title="PEP 702 Marking deprecations using the type system">PEP 702</a>.</li>
<li>2023-Jul-03: Added the Soft Deprecation section, as discussed in
<a class="reference external" href="https://discuss.python.org/t/27957">https://discuss.python.org/t/27957</a>.</li>
<li>2023-Jun-26: Multiple smaller updates and clarifications, discussed in
<a class="reference external" href="https://discuss.python.org/t/22042">https://discuss.python.org/t/22042</a>.</li>
<li>2022-Apr-04: Added explicit notes to ask the Steering Council
in several exceptional cases.</li>
<li>2021-Apr-16: Clarified how long a warning must be emitted before
a change can be made.</li>
<li>2020-Jul-20: Initial accepted version.</li>
</ul>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="tiobe" role="doc-footnote">
<dt class="label" id="tiobe">[<a href="#id1">1</a>]</dt>
<dd>TIOBE Programming Community Index<p><a class="reference external" href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html">http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html</a></p>
</aside>
<aside class="footnote brackets" id="warnings" role="doc-footnote">
<dt class="label" id="warnings">[<a href="#id2">2</a>]</dt>
<dd>The warnings module<p><a class="reference external" href="http://docs.python.org/library/warnings.html">http://docs.python.org/library/warnings.html</a></p>
</aside>
</aside>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0387.rst">https://github.com/python/peps/blob/main/peps/pep-0387.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0387.rst">2024-10-10 20:00:57 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="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#backwards-compatibility-rules">Backwards Compatibility Rules</a><ul>
<li><a class="reference internal" href="#basic-policy-for-backwards-compatibility">Basic policy for backwards compatibility</a></li>
</ul>
</li>
<li><a class="reference internal" href="#soft-deprecation">Soft Deprecation</a></li>
<li><a class="reference internal" href="#making-incompatible-changes">Making Incompatible Changes</a></li>
<li><a class="reference internal" href="#changelog">Changelog</a></li>
<li><a class="reference internal" href="#references">References</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-0387.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>