Skip to content

Commit 90c1d86

Browse files
authored
gh-149609: Raise deprecation warnings for abc.{abstractclassmethod,abstractstaticmethod,abstractproperty} (#149636)
1 parent 73d8e9a commit 90c1d86

10 files changed

Lines changed: 107 additions & 18 deletions

File tree

Doc/deprecations/pending-removal-in-3.21.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
Pending removal in Python 3.21
22
------------------------------
33

4+
* :mod:`abc`
5+
6+
* Soft-deprecated since Python 3.3 :class:`abc.abstractclassmethod`,
7+
:class:`abc.abstractstaticmethod`, and :class:`abc.abstractproperty`
8+
now raise a :exc:`DeprecationWarning`.
9+
These classes will be removed in Python 3.21, instead
10+
use :func:`abc.abstractmethod` with :func:`classmethod`,
11+
:func:`staticmethod`, and :class:`property` respectively.
12+
413
* :mod:`ast`:
514

615
* Classes ``slice``, ``Index``, ``ExtSlice``, ``Suite``, ``Param``,

Doc/library/abc.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ The :mod:`!abc` module also supports the following legacy decorators:
237237
.. decorator:: abstractclassmethod
238238

239239
.. versionadded:: 3.2
240-
.. deprecated:: 3.3
240+
.. deprecated-removed:: 3.3 3.21
241241
It is now possible to use :class:`classmethod` with
242242
:func:`abstractmethod`, making this decorator redundant.
243243

@@ -258,7 +258,7 @@ The :mod:`!abc` module also supports the following legacy decorators:
258258
.. decorator:: abstractstaticmethod
259259

260260
.. versionadded:: 3.2
261-
.. deprecated:: 3.3
261+
.. deprecated-removed:: 3.3 3.21
262262
It is now possible to use :class:`staticmethod` with
263263
:func:`abstractmethod`, making this decorator redundant.
264264

@@ -278,7 +278,7 @@ The :mod:`!abc` module also supports the following legacy decorators:
278278

279279
.. decorator:: abstractproperty
280280

281-
.. deprecated:: 3.3
281+
.. deprecated-removed:: 3.3 3.21
282282
It is now possible to use :class:`property`, :meth:`property.getter`,
283283
:meth:`property.setter` and :meth:`property.deleter` with
284284
:func:`abstractmethod`, making this decorator redundant.

Doc/whatsnew/3.12.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1367,6 +1367,8 @@ Deprecated
13671367

13681368
.. include:: ../deprecations/pending-removal-in-3.20.rst
13691369

1370+
.. include:: ../deprecations/pending-removal-in-3.21.rst
1371+
13701372
.. include:: ../deprecations/pending-removal-in-future.rst
13711373

13721374
.. _whatsnew312-removed:

Doc/whatsnew/3.13.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2031,6 +2031,8 @@ New Deprecations
20312031

20322032
.. include:: ../deprecations/pending-removal-in-3.20.rst
20332033

2034+
.. include:: ../deprecations/pending-removal-in-3.21.rst
2035+
20342036
.. include:: ../deprecations/pending-removal-in-future.rst
20352037

20362038
CPython Bytecode Changes

Doc/whatsnew/3.14.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2748,6 +2748,8 @@ New deprecations
27482748

27492749
.. include:: ../deprecations/pending-removal-in-3.20.rst
27502750

2751+
.. include:: ../deprecations/pending-removal-in-3.21.rst
2752+
27512753
.. include:: ../deprecations/pending-removal-in-future.rst
27522754

27532755

Doc/whatsnew/3.15.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2335,6 +2335,8 @@ New deprecations
23352335

23362336
.. include:: ../deprecations/pending-removal-in-3.20.rst
23372337

2338+
.. include:: ../deprecations/pending-removal-in-3.21.rst
2339+
23382340
.. include:: ../deprecations/pending-removal-in-future.rst
23392341

23402342
.. include:: ../deprecations/soft-deprecations.rst

Doc/whatsnew/3.16.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,15 @@ tarfile
215215
Deprecated
216216
==========
217217

218+
* :mod:`abc`
219+
220+
* Soft-deprecated since Python 3.3 :class:`abc.abstractclassmethod`,
221+
:class:`abc.abstractstaticmethod`, and :class:`abc.abstractproperty`
222+
now raise a :exc:`DeprecationWarning`.
223+
These classes will be removed in Python 3.21, instead
224+
use :func:`abc.abstractmethod` with :func:`classmethod`,
225+
:func:`staticmethod`, and :class:`property` respectively.
226+
218227
* :mod:`ast`:
219228

220229
* Classes ``slice``, ``Index``, ``ExtSlice``, ``Suite``, ``Param``,
@@ -228,6 +237,14 @@ Deprecated
228237

229238
.. Add deprecations above alphabetically, not here at the end.
230239
240+
.. include:: ../deprecations/pending-removal-in-3.17.rst
241+
242+
.. include:: ../deprecations/pending-removal-in-3.19.rst
243+
244+
.. include:: ../deprecations/pending-removal-in-3.20.rst
245+
246+
.. include:: ../deprecations/pending-removal-in-future.rst
247+
231248

232249
Porting to Python 3.16
233250
======================

Lib/abc.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,15 @@ class C(ABC):
3636
def my_abstract_classmethod(cls, ...):
3737
...
3838
39+
.. deprecated-removed: 3.3 3.21
40+
3941
"""
4042

4143
__isabstractmethod__ = True
4244

4345
def __init__(self, callable):
46+
import warnings
47+
warnings._deprecated('abc.abstractclassmethod', remove=(3, 21))
4448
callable.__isabstractmethod__ = True
4549
super().__init__(callable)
4650

@@ -56,11 +60,15 @@ class C(ABC):
5660
def my_abstract_staticmethod(...):
5761
...
5862
63+
.. deprecated-removed: 3.3 3.21
64+
5965
"""
6066

6167
__isabstractmethod__ = True
6268

6369
def __init__(self, callable):
70+
import warnings
71+
warnings._deprecated('abc.abstractstaticmethod', remove=(3, 21))
6472
callable.__isabstractmethod__ = True
6573
super().__init__(callable)
6674

@@ -76,10 +84,23 @@ class C(ABC):
7684
def my_abstract_property(self):
7785
...
7886
87+
.. deprecated-removed: 3.3 3.21
88+
7989
"""
8090

8191
__isabstractmethod__ = True
8292

93+
def __init__(
94+
self,
95+
fget=None,
96+
fset=None,
97+
fdel=None,
98+
doc=None,
99+
):
100+
import warnings
101+
warnings._deprecated('abc.abstractproperty', remove=(3, 21))
102+
super().__init__(fget, fset, fdel, doc)
103+
83104

84105
try:
85106
from _abc import (get_cache_token, _abc_init, _abc_register,

Lib/test/test_abc.py

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,30 @@
1111
import abc
1212
import _py_abc
1313
from inspect import isabstract
14+
from test.support import warnings_helper
1415

1516
def test_factory(abc_ABCMeta, abc_get_cache_token):
1617
class TestLegacyAPI(unittest.TestCase):
1718

1819
def test_abstractproperty_basics(self):
19-
@abc.abstractproperty
20-
def foo(self): pass
20+
with self.assertWarnsRegex(
21+
DeprecationWarning,
22+
'abstractproperty',
23+
):
24+
@abc.abstractproperty
25+
def foo(self): pass
26+
2127
self.assertTrue(foo.__isabstractmethod__)
2228
def bar(self): pass
2329
self.assertNotHasAttr(bar, "__isabstractmethod__")
2430

25-
class C(metaclass=abc_ABCMeta):
26-
@abc.abstractproperty
27-
def foo(self): return 3
31+
with self.assertWarnsRegex(
32+
DeprecationWarning,
33+
'abstractproperty',
34+
):
35+
class C(metaclass=abc_ABCMeta):
36+
@abc.abstractproperty
37+
def foo(self): return 3
2838
self.assertRaises(TypeError, C)
2939
class D(C):
3040
@property
@@ -33,16 +43,26 @@ def foo(self): return super().foo
3343
self.assertFalse(getattr(D.foo, "__isabstractmethod__", False))
3444

3545
def test_abstractclassmethod_basics(self):
36-
@abc.abstractclassmethod
37-
def foo(cls): pass
46+
with self.assertWarnsRegex(
47+
DeprecationWarning,
48+
'abstractclassmethod',
49+
):
50+
@abc.abstractclassmethod
51+
def foo(cls): pass
52+
3853
self.assertTrue(foo.__isabstractmethod__)
3954
@classmethod
4055
def bar(cls): pass
4156
self.assertFalse(getattr(bar, "__isabstractmethod__", False))
4257

43-
class C(metaclass=abc_ABCMeta):
44-
@abc.abstractclassmethod
45-
def foo(cls): return cls.__name__
58+
with self.assertWarnsRegex(
59+
DeprecationWarning,
60+
'abstractclassmethod',
61+
):
62+
class C(metaclass=abc_ABCMeta):
63+
@abc.abstractclassmethod
64+
def foo(cls): return cls.__name__
65+
4666
self.assertRaises(TypeError, C)
4767
class D(C):
4868
@classmethod
@@ -51,16 +71,26 @@ def foo(cls): return super().foo()
5171
self.assertEqual(D().foo(), 'D')
5272

5373
def test_abstractstaticmethod_basics(self):
54-
@abc.abstractstaticmethod
55-
def foo(): pass
74+
with self.assertWarnsRegex(
75+
DeprecationWarning,
76+
'abstractstaticmethod',
77+
):
78+
@abc.abstractstaticmethod
79+
def foo(): pass
80+
5681
self.assertTrue(foo.__isabstractmethod__)
5782
@staticmethod
5883
def bar(): pass
5984
self.assertFalse(getattr(bar, "__isabstractmethod__", False))
6085

61-
class C(metaclass=abc_ABCMeta):
62-
@abc.abstractstaticmethod
63-
def foo(): return 3
86+
with self.assertWarnsRegex(
87+
DeprecationWarning,
88+
'abstractstaticmethod',
89+
):
90+
class C(metaclass=abc_ABCMeta):
91+
@abc.abstractstaticmethod
92+
def foo(): return 3
93+
6494
self.assertRaises(TypeError, C)
6595
class D(C):
6696
@staticmethod
@@ -168,6 +198,7 @@ def method_two(self):
168198
msg = r"class C without an implementation for abstract methods 'method_one', 'method_two'"
169199
self.assertRaisesRegex(TypeError, msg, C)
170200

201+
@warnings_helper.ignore_warnings(category=DeprecationWarning)
171202
def test_abstractmethod_integration(self):
172203
for abstractthing in [abc.abstractmethod, abc.abstractproperty,
173204
abc.abstractclassmethod,
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Raise :exc:`DeprecationWarning` on using :class:`abc.abstractclassmethod`,
2+
:class:`abc.abstractstaticmethod`, and :class:`abc.abstractproperty`,
3+
schedule its removal for Python 3.21.

0 commit comments

Comments
 (0)