330 lines
20 KiB
HTML
330 lines
20 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 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 Python’s 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 Python’s 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> » </li>
|
||
<li><a href="../pep-0000/">PEP Index</a> » </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 <benjamin at python.org></dd>
|
||
<dt class="field-even">PEP-Delegate<span class="colon">:</span></dt>
|
||
<dd class="field-even">Brett Cannon <brett at python.org></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@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 Python’s 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. Python’s 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:
|
||
it’s 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">@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>It’s 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 there’s 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">@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> |