Notice: While Javascript is not essential for this website, your interaction with the content will be limited. Please turn Javascript on for the full experience.

PEP 387 -- Backwards Compatibility Policy

PEP:387
Title:Backwards Compatibility Policy
Author:Benjamin Peterson <benjamin at python.org>
BDFL-Delegate:Brett Cannon (on behalf of the steering council)
Discussions-To:https://discuss.python.org/t/pep-387-backwards-compatibilty-policy/
Status:Draft
Type:Process
Created:18-Jun-2009
Post-History:19-Jun-2009, 12-Jun-2020

Abstract

This PEP outlines Python's backwards compatibility policy.

Rationale

As one of the most used programming languages today [1], 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.
  • 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.)

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

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 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.
  2. Add a warning. 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 were the old and new versions of the API will coexist for many releases [2]. Compiler warnings are also acceptable. 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.
  3. Wait for the warning to appear in at least two major Python versions. It's fine to wait more than two releases.
  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.
Source: https://github.com/python/peps/blob/master/pep-0387.txt