PEP: 387
Title: Backwards Compatibility Policy
Author: Benjamin Peterson <benjamin@python.org>
PEP-Delegate: Brett Cannon <brett@python.org>
Status: Active
Type: Process
Created: 18-Jun-2009
Post-History: `19-Jun-2009 <https://mail.python.org/archives/list/python-dev@python.org/thread/YAZQHFUCYEYIX5MIG6LFJLCVQ5ORVUM6/>`__,
              `12-Jun-2020 <https://discuss.python.org/t/pep-387-backwards-compatibilty-policy/4421>`__,
              `19-Dec-2022 <https://discuss.python.org/t/22042>`__,
              `16-Jun-2023 <https://discuss.python.org/t/formalize-the-concept-of-soft-deprecation-dont-schedule-removal-in-pep-387-backwards-compatibility-policy/27957>`__
Replaces: 291


Abstract
========

This PEP outlines Python's backwards compatibility policy.


Rationale
=========

As one of the most used programming languages today [#tiobe]_, 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.

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.


Backwards Compatibility Rules
=============================

This policy applies to all public APIs.  These include:

- Syntax and behavior of these constructs as defined by the reference
  manual.

- The C-API.

- Function, class, module, attribute, and method names and types.

- 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.

- The position and expected types of arguments and returned values.

- Behavior of classes with regards to subclasses: the conditions under
  which overridden methods are called.

- Documented exceptions and the semantics which lead to their raising.

- Exceptions commonly raised in EAFP scenarios.

Others are explicitly not part of the public API.  They can change or
be removed at any time in any way.  These include:

- Function, class, module, attribute, method, and C-API names and
  types that are prefixed by "_" (except special names).

- Anything documented publicly as being private.
  Note that if something is not documented at all, it is *not*
  automatically considered private.

- Imported modules (unless explicitly documented as part of the public
  API; e.g. importing the ``bacon`` module in the ``spam`` does not
  automatically mean ``spam.bacon`` is part of the public API unless
  it is documented as such).

- Inheritance patterns of internal classes.

- Test suites.  (Anything in the ``Lib/test`` directory or test
  subdirectories of packages.)

- Backward compatibility rules do not apply to any module or API that is
  explicitly documented as **Provisional** per :pep:`411`.


Basic policy for backwards compatibility
----------------------------------------

* 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.

* Unless it is going through the deprecation process below, the
  behavior of an API *must* not change in an incompatible fashion
  between any two consecutive releases.  Python's yearly release
  process (:pep:`602`) means that the deprecation period must last at
  least two years.

* Similarly a feature cannot be removed without notice between any two
  consecutive releases.

* For changes that are unable to raise a deprecation warning, consult
  with the steering council.

* 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).


.. _pep387-soft-deprecation:

Soft Deprecation
================

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).

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.

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 ``DeprecationWarning`` warning at runtime. The
documentation of a soft deprecation should explain why the API should be
avoided, and if possible propose a replacement.

If the decision is made to deprecate (in the regular sense) a feature
that is currently soft deprecated, the deprecation must follow the
`Backwards Compatibility Rules`_ (i.e., there is no exception because
the feature is already soft deprecated).


Making Incompatible Changes
===========================

Making an incompatible change is a gradual process performed over
several releases:

1. Discuss the change.
   Depending on the degree of incompatibility, this could be on
   `Discourse <https://discuss.python.org/>`__,
   the `issue tracker <https://github.com/python/cpython/issues/>`__,
   or in an appropriate workgroup or SIG.
   If the discussion reaches consensus a :pep:`PEP <1>` or
   similar document may be written.
   Hopefully users of the affected API will pipe up to comment.

2. Add a warning to the current ``main`` 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.  ``DeprecationWarning`` is the usual
   warning category to use, but ``PendingDeprecationWarning`` may be
   used in special cases where the old and new versions of the API will
   coexist for many releases [#warnings]_.  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 `typeshed <https://github.com/python/typeshed>`_
   to add the ``@deprecated`` decorator (see :pep:`702`) to the deprecated API,
   so that users of static type checkers have another way to learn
   about the deprecation.

   For C API, a compiler warning generated by the ``Py_DEPRECATED`` macro
   is also acceptable.

3. 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). It is
   preferred, though, to wait 5 years before removal (e.g., warn starting in
   Python 3.10, removal in 3.15; this happens to coincide with the current
   lifetime of a minor release of Python).

   - 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).

   - If the deprecated feature is replaced by a new one, it should
     generally be removed only after the last Python version
     *without* the new feature reaches end of support.

4. See if there's any feedback.  Users not involved in the original
   discussions may comment now after seeing the warning.  Perhaps
   reconsider.

5. The behavior change or feature removal may now be made default or
   permanent having reached the declared version. Remove the old
   version and warning.

6. If a warning cannot be provided to users, consult with the steering
   council.


Changelog
=========

* 2025-Jan-27: Updated to prefer a 5-year deprecation period before removal.
* 2023-Nov-14: Added ``@deprecated`` decorator per :pep:`702`.
* 2023-Jul-03: Added the Soft Deprecation section, as discussed in
  `<https://discuss.python.org/t/27957>`__.
* 2023-Jun-26: Multiple smaller updates and clarifications, discussed in
  `<https://discuss.python.org/t/22042>`__.
* 2022-Apr-04: Added explicit notes to ask the Steering Council
  in several exceptional cases.
* 2021-Apr-16: Clarified how long a warning must be emitted before
  a change can be made.
* 2020-Jul-20: Initial accepted version.


References
==========

.. [#tiobe] TIOBE Programming Community Index

   https://www.tiobe.com/tiobe-index/

.. [#warnings] The warnings module

   http://docs.python.org/library/warnings.html


Copyright
=========

This document has been placed in the public domain.
