https://github.com/python/cpython/commit/90c1d86f34355fa88104f1ec81ce9d82ccd7963c
commit: 90c1d86f34355fa88104f1ec81ce9d82ccd7963c
branch: main
author: sobolevn <[email protected]>
committer: sobolevn <[email protected]>
date: 2026-05-31T07:26:52Z
summary:
gh-149609: Raise deprecation warnings for
`abc.{abstractclassmethod,abstractstaticmethod,abstractproperty}` (#149636)
files:
A Misc/NEWS.d/next/Library/2026-05-10-16-06-27.gh-issue-149609.yLKPXo.rst
M Doc/deprecations/pending-removal-in-3.21.rst
M Doc/library/abc.rst
M Doc/whatsnew/3.12.rst
M Doc/whatsnew/3.13.rst
M Doc/whatsnew/3.14.rst
M Doc/whatsnew/3.15.rst
M Doc/whatsnew/3.16.rst
M Lib/abc.py
M Lib/test/test_abc.py
diff --git a/Doc/deprecations/pending-removal-in-3.21.rst
b/Doc/deprecations/pending-removal-in-3.21.rst
index 5d0c56612094ff4..18b89a20e4a2082 100644
--- a/Doc/deprecations/pending-removal-in-3.21.rst
+++ b/Doc/deprecations/pending-removal-in-3.21.rst
@@ -1,6 +1,15 @@
Pending removal in Python 3.21
------------------------------
+* :mod:`abc`
+
+ * Soft-deprecated since Python 3.3 :class:`abc.abstractclassmethod`,
+ :class:`abc.abstractstaticmethod`, and :class:`abc.abstractproperty`
+ now raise a :exc:`DeprecationWarning`.
+ These classes will be removed in Python 3.21, instead
+ use :func:`abc.abstractmethod` with :func:`classmethod`,
+ :func:`staticmethod`, and :class:`property` respectively.
+
* :mod:`ast`:
* Classes ``slice``, ``Index``, ``ExtSlice``, ``Suite``, ``Param``,
diff --git a/Doc/library/abc.rst b/Doc/library/abc.rst
index 8112cfee7d204db..904eff2e31e6ac2 100644
--- a/Doc/library/abc.rst
+++ b/Doc/library/abc.rst
@@ -237,7 +237,7 @@ The :mod:`!abc` module also supports the following legacy
decorators:
.. decorator:: abstractclassmethod
.. versionadded:: 3.2
- .. deprecated:: 3.3
+ .. deprecated-removed:: 3.3 3.21
It is now possible to use :class:`classmethod` with
:func:`abstractmethod`, making this decorator redundant.
@@ -258,7 +258,7 @@ The :mod:`!abc` module also supports the following legacy
decorators:
.. decorator:: abstractstaticmethod
.. versionadded:: 3.2
- .. deprecated:: 3.3
+ .. deprecated-removed:: 3.3 3.21
It is now possible to use :class:`staticmethod` with
:func:`abstractmethod`, making this decorator redundant.
@@ -278,7 +278,7 @@ The :mod:`!abc` module also supports the following legacy
decorators:
.. decorator:: abstractproperty
- .. deprecated:: 3.3
+ .. deprecated-removed:: 3.3 3.21
It is now possible to use :class:`property`, :meth:`property.getter`,
:meth:`property.setter` and :meth:`property.deleter` with
:func:`abstractmethod`, making this decorator redundant.
diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst
index df6cc98eaf1c90a..0378ada72804c9e 100644
--- a/Doc/whatsnew/3.12.rst
+++ b/Doc/whatsnew/3.12.rst
@@ -1367,6 +1367,8 @@ Deprecated
.. include:: ../deprecations/pending-removal-in-3.20.rst
+.. include:: ../deprecations/pending-removal-in-3.21.rst
+
.. include:: ../deprecations/pending-removal-in-future.rst
.. _whatsnew312-removed:
diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst
index 4272c04d80868bb..0db8ec55e5c9f8e 100644
--- a/Doc/whatsnew/3.13.rst
+++ b/Doc/whatsnew/3.13.rst
@@ -2031,6 +2031,8 @@ New Deprecations
.. include:: ../deprecations/pending-removal-in-3.20.rst
+.. include:: ../deprecations/pending-removal-in-3.21.rst
+
.. include:: ../deprecations/pending-removal-in-future.rst
CPython Bytecode Changes
diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst
index 39d1d8da5367e5e..cd0d8b7cb006fee 100644
--- a/Doc/whatsnew/3.14.rst
+++ b/Doc/whatsnew/3.14.rst
@@ -2748,6 +2748,8 @@ New deprecations
.. include:: ../deprecations/pending-removal-in-3.20.rst
+.. include:: ../deprecations/pending-removal-in-3.21.rst
+
.. include:: ../deprecations/pending-removal-in-future.rst
diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst
index 8e6b1faa523f68e..1d27baf38906e9a 100644
--- a/Doc/whatsnew/3.15.rst
+++ b/Doc/whatsnew/3.15.rst
@@ -2335,6 +2335,8 @@ New deprecations
.. include:: ../deprecations/pending-removal-in-3.20.rst
+.. include:: ../deprecations/pending-removal-in-3.21.rst
+
.. include:: ../deprecations/pending-removal-in-future.rst
.. include:: ../deprecations/soft-deprecations.rst
diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst
index a6911b68c2eb756..9a0a0d3d8831f5f 100644
--- a/Doc/whatsnew/3.16.rst
+++ b/Doc/whatsnew/3.16.rst
@@ -215,6 +215,15 @@ tarfile
Deprecated
==========
+* :mod:`abc`
+
+ * Soft-deprecated since Python 3.3 :class:`abc.abstractclassmethod`,
+ :class:`abc.abstractstaticmethod`, and :class:`abc.abstractproperty`
+ now raise a :exc:`DeprecationWarning`.
+ These classes will be removed in Python 3.21, instead
+ use :func:`abc.abstractmethod` with :func:`classmethod`,
+ :func:`staticmethod`, and :class:`property` respectively.
+
* :mod:`ast`:
* Classes ``slice``, ``Index``, ``ExtSlice``, ``Suite``, ``Param``,
@@ -228,6 +237,14 @@ Deprecated
.. Add deprecations above alphabetically, not here at the end.
+.. include:: ../deprecations/pending-removal-in-3.17.rst
+
+.. include:: ../deprecations/pending-removal-in-3.19.rst
+
+.. include:: ../deprecations/pending-removal-in-3.20.rst
+
+.. include:: ../deprecations/pending-removal-in-future.rst
+
Porting to Python 3.16
======================
diff --git a/Lib/abc.py b/Lib/abc.py
index f8a4e11ce9c3b1e..08f708d1b892085 100644
--- a/Lib/abc.py
+++ b/Lib/abc.py
@@ -36,11 +36,15 @@ class C(ABC):
def my_abstract_classmethod(cls, ...):
...
+ .. deprecated-removed: 3.3 3.21
+
"""
__isabstractmethod__ = True
def __init__(self, callable):
+ import warnings
+ warnings._deprecated('abc.abstractclassmethod', remove=(3, 21))
callable.__isabstractmethod__ = True
super().__init__(callable)
@@ -56,11 +60,15 @@ class C(ABC):
def my_abstract_staticmethod(...):
...
+ .. deprecated-removed: 3.3 3.21
+
"""
__isabstractmethod__ = True
def __init__(self, callable):
+ import warnings
+ warnings._deprecated('abc.abstractstaticmethod', remove=(3, 21))
callable.__isabstractmethod__ = True
super().__init__(callable)
@@ -76,10 +84,23 @@ class C(ABC):
def my_abstract_property(self):
...
+ .. deprecated-removed: 3.3 3.21
+
"""
__isabstractmethod__ = True
+ def __init__(
+ self,
+ fget=None,
+ fset=None,
+ fdel=None,
+ doc=None,
+ ):
+ import warnings
+ warnings._deprecated('abc.abstractproperty', remove=(3, 21))
+ super().__init__(fget, fset, fdel, doc)
+
try:
from _abc import (get_cache_token, _abc_init, _abc_register,
diff --git a/Lib/test/test_abc.py b/Lib/test/test_abc.py
index 80ee9e0ba56e754..59a45a2eda07b00 100644
--- a/Lib/test/test_abc.py
+++ b/Lib/test/test_abc.py
@@ -11,20 +11,30 @@
import abc
import _py_abc
from inspect import isabstract
+from test.support import warnings_helper
def test_factory(abc_ABCMeta, abc_get_cache_token):
class TestLegacyAPI(unittest.TestCase):
def test_abstractproperty_basics(self):
- @abc.abstractproperty
- def foo(self): pass
+ with self.assertWarnsRegex(
+ DeprecationWarning,
+ 'abstractproperty',
+ ):
+ @abc.abstractproperty
+ def foo(self): pass
+
self.assertTrue(foo.__isabstractmethod__)
def bar(self): pass
self.assertNotHasAttr(bar, "__isabstractmethod__")
- class C(metaclass=abc_ABCMeta):
- @abc.abstractproperty
- def foo(self): return 3
+ with self.assertWarnsRegex(
+ DeprecationWarning,
+ 'abstractproperty',
+ ):
+ class C(metaclass=abc_ABCMeta):
+ @abc.abstractproperty
+ def foo(self): return 3
self.assertRaises(TypeError, C)
class D(C):
@property
@@ -33,16 +43,26 @@ def foo(self): return super().foo
self.assertFalse(getattr(D.foo, "__isabstractmethod__", False))
def test_abstractclassmethod_basics(self):
- @abc.abstractclassmethod
- def foo(cls): pass
+ with self.assertWarnsRegex(
+ DeprecationWarning,
+ 'abstractclassmethod',
+ ):
+ @abc.abstractclassmethod
+ def foo(cls): pass
+
self.assertTrue(foo.__isabstractmethod__)
@classmethod
def bar(cls): pass
self.assertFalse(getattr(bar, "__isabstractmethod__", False))
- class C(metaclass=abc_ABCMeta):
- @abc.abstractclassmethod
- def foo(cls): return cls.__name__
+ with self.assertWarnsRegex(
+ DeprecationWarning,
+ 'abstractclassmethod',
+ ):
+ class C(metaclass=abc_ABCMeta):
+ @abc.abstractclassmethod
+ def foo(cls): return cls.__name__
+
self.assertRaises(TypeError, C)
class D(C):
@classmethod
@@ -51,16 +71,26 @@ def foo(cls): return super().foo()
self.assertEqual(D().foo(), 'D')
def test_abstractstaticmethod_basics(self):
- @abc.abstractstaticmethod
- def foo(): pass
+ with self.assertWarnsRegex(
+ DeprecationWarning,
+ 'abstractstaticmethod',
+ ):
+ @abc.abstractstaticmethod
+ def foo(): pass
+
self.assertTrue(foo.__isabstractmethod__)
@staticmethod
def bar(): pass
self.assertFalse(getattr(bar, "__isabstractmethod__", False))
- class C(metaclass=abc_ABCMeta):
- @abc.abstractstaticmethod
- def foo(): return 3
+ with self.assertWarnsRegex(
+ DeprecationWarning,
+ 'abstractstaticmethod',
+ ):
+ class C(metaclass=abc_ABCMeta):
+ @abc.abstractstaticmethod
+ def foo(): return 3
+
self.assertRaises(TypeError, C)
class D(C):
@staticmethod
@@ -168,6 +198,7 @@ def method_two(self):
msg = r"class C without an implementation for abstract methods
'method_one', 'method_two'"
self.assertRaisesRegex(TypeError, msg, C)
+ @warnings_helper.ignore_warnings(category=DeprecationWarning)
def test_abstractmethod_integration(self):
for abstractthing in [abc.abstractmethod, abc.abstractproperty,
abc.abstractclassmethod,
diff --git
a/Misc/NEWS.d/next/Library/2026-05-10-16-06-27.gh-issue-149609.yLKPXo.rst
b/Misc/NEWS.d/next/Library/2026-05-10-16-06-27.gh-issue-149609.yLKPXo.rst
new file mode 100644
index 000000000000000..3acba7d25021b28
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-05-10-16-06-27.gh-issue-149609.yLKPXo.rst
@@ -0,0 +1,3 @@
+Raise :exc:`DeprecationWarning` on using :class:`abc.abstractclassmethod`,
+:class:`abc.abstractstaticmethod`, and :class:`abc.abstractproperty`,
+schedule its removal for Python 3.21.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]