formerly renames a class that users inherit from, without breaking them.
Install with:
pip install formerly
Usage
Rename the class, and leave the old name behind as an alias:
from formerly import deprecated_class
class NewName(SomeClass): ...
OldName = deprecated_class("OldName", NewName)
Now:
Subclassing OldName warns, pointing at the class statement.
Instantiating OldName warns, but instantiating a subclass does not: the subclass author gets one warning where the problem is, not one per object.
issubclass() and isinstance() checks against OldName accept subclasses of NewName, so code that has already migrated keeps passing the checks of code that has not.
OldName is a real class: it pickles, survives copy.deepcopy(), passes inspect.isclass(), and can be registered with an abc.ABCMeta interface.
Type checkers reject a base class that comes from a variable, so users subclassing the alias need OldName: Any = ... on their side, or a per-statement ignore comment.
Warnings use DeprecationWarning and report the paths of the classes involved. Both are configurable, along with the messages themselves:
OldName = deprecated_class(
"OldName",
NewName,
category=MyLibraryDeprecationWarning,
new_path="mylibrary.NewName",
subclass_message="{cls} inherits from {old}, which is going away in 3.0.",
)
By default only the first subclass warns, since one warning is enough to tell users to migrate. Pass warn_once=False to warn on every subclass.
See the deprecated_class() docstring for the full signature.
Alternatives
Renaming a base class asks more of a deprecation helper than renaming a function does. Each row below is a behavior that a class users inherit from needs:
formerly |
|||||
|---|---|---|---|---|---|
Warns where the subclass is defined |
✔ |
✔ |
✘ |
✘ |
✘ |
Stays quiet when a subclass is instantiated |
✔ |
✔ |
✘ |
✘ |
✘ |
Warns when the old name is instantiated |
✔ |
✔ |
✔ |
✔ |
✔ |
Accepts migrated classes in issubclass() and isinstance() |
✔ |
✘ |
✘ |
✘ |
✔ |
Is a class: pickle, deepcopy, inspect.isclass(), abc |
✔ |
✔ |
✔ |
✔ |
✘ |
Reported by type checkers |
✘ |
✔ |
✘ |
✘ |
✘ |
Only the fourth row is unique to formerly: the old name keeps accepting classes that already inherit from the new one, so a library can rename a base class without breaking the isinstance() checks that its own code, or its users’ code, runs against the old name.
If nothing checks types against the old name, warnings.deprecated covers the rest, and adds what formerly cannot: type checkers report the deprecation before the code runs. It needs Python 3.13, or typing_extensions for older versions, which behaves identically.
Measured on Python 3.13 against Deprecated 1.3.1, debtcollector 3.1.0 and pyDeprecate 0.11.0. pyDeprecate wraps the class in a proxy object rather than a class, so subclassing it raises TypeError.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file formerly-0.1.0.tar.gz.
File metadata
- Download URL: formerly-0.1.0.tar.gz
- Upload date:
- Size: 8.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e30ce1f317b3a05689aea057faa3bc4ec89a105ba5a48433ca9899ac1bf69a62
|
|
| MD5 |
9c66ca5bf296659c0a33f88635c12e3e
|
|
| BLAKE2b-256 |
7f7b7bab9bed04fb9f08e0e8c9081e5ca0068d40bb913260f09b28b643876528
|
Provenance
The following attestation bundles were made for formerly-0.1.0.tar.gz:
Publisher:
publish.yml on scrapy/formerly
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
formerly-0.1.0.tar.gz -
Subject digest:
e30ce1f317b3a05689aea057faa3bc4ec89a105ba5a48433ca9899ac1bf69a62 - Sigstore transparency entry: 2347446929
- Sigstore integration time:
-
Permalink:
scrapy/formerly@16cb43b68efd7862322b1d1bbd6a397f0a357a0f -
Branch / Tag:
refs/tags/0.1.0 - Owner: https://github.com/scrapy
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@16cb43b68efd7862322b1d1bbd6a397f0a357a0f -
Trigger Event:
push
-
Statement type:
File details
Details for the file formerly-0.1.0-py3-none-any.whl.
File metadata
- Download URL: formerly-0.1.0-py3-none-any.whl
- Upload date:
- Size: 5.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
96dc14b85d8288eda824fa1f1521a1b070252fea9fb17d2bc7134c6661b7c556
|
|
| MD5 |
01f7d0467d9f84e15fa19f51ab376357
|
|
| BLAKE2b-256 |
9c2199cb05c0928fce1bd1b22a873d7ac94847af789ca35a43e34e9c34ded0f4
|
Provenance
The following attestation bundles were made for formerly-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on scrapy/formerly
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
formerly-0.1.0-py3-none-any.whl -
Subject digest:
96dc14b85d8288eda824fa1f1521a1b070252fea9fb17d2bc7134c6661b7c556 - Sigstore transparency entry: 2347447009
- Sigstore integration time:
-
Permalink:
scrapy/formerly@16cb43b68efd7862322b1d1bbd6a397f0a357a0f -
Branch / Tag:
refs/tags/0.1.0 - Owner: https://github.com/scrapy
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@16cb43b68efd7862322b1d1bbd6a397f0a357a0f -
Trigger Event:
push
-
Statement type: