Skip to content

Commit b1302ab

Browse files
bpo-44904: Fix classmethod property bug in doctest module (pythonGH-28838)
The doctest module raised an error if a docstring contained an example that attempted to access a classmethod property. (Stacking '@classmethod' on top of `@property` has been supported since Python 3.9; see https://docs.python.org/3/howto/descriptor.html#class-methods.) Co-authored-by: Serhiy Storchaka <[email protected]>
1 parent d02ffd1 commit b1302ab

File tree

4 files changed

+21
-4
lines changed

4 files changed

+21
-4
lines changed

Lib/doctest.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,10 +1034,8 @@ def _find(self, tests, obj, name, module, source_lines, globs, seen):
10341034
if inspect.isclass(obj) and self._recurse:
10351035
for valname, val in obj.__dict__.items():
10361036
# Special handling for staticmethod/classmethod.
1037-
if isinstance(val, staticmethod):
1038-
val = getattr(obj, valname)
1039-
if isinstance(val, classmethod):
1040-
val = getattr(obj, valname).__func__
1037+
if isinstance(val, (staticmethod, classmethod)):
1038+
val = val.__func__
10411039

10421040
# Recurse to methods, properties, and nested classes.
10431041
if ((inspect.isroutine(val) or inspect.isclass(val) or

Lib/test/test_doctest.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,17 @@ def a_classmethod(cls, v):
9696
22
9797
""")
9898

99+
a_class_attribute = 42
100+
101+
@classmethod
102+
@property
103+
def a_classmethod_property(cls):
104+
"""
105+
>>> print(SampleClass.a_classmethod_property)
106+
42
107+
"""
108+
return cls.a_class_attribute
109+
99110
class NestedClass:
100111
"""
101112
>>> x = SampleClass.NestedClass(5)
@@ -501,6 +512,7 @@ def basics(): r"""
501512
1 SampleClass.NestedClass.__init__
502513
1 SampleClass.__init__
503514
2 SampleClass.a_classmethod
515+
1 SampleClass.a_classmethod_property
504516
1 SampleClass.a_property
505517
1 SampleClass.a_staticmethod
506518
1 SampleClass.double
@@ -556,6 +568,7 @@ def basics(): r"""
556568
1 some_module.SampleClass.NestedClass.__init__
557569
1 some_module.SampleClass.__init__
558570
2 some_module.SampleClass.a_classmethod
571+
1 some_module.SampleClass.a_classmethod_property
559572
1 some_module.SampleClass.a_property
560573
1 some_module.SampleClass.a_staticmethod
561574
1 some_module.SampleClass.double
@@ -597,6 +610,7 @@ def basics(): r"""
597610
1 SampleClass.NestedClass.__init__
598611
1 SampleClass.__init__
599612
2 SampleClass.a_classmethod
613+
1 SampleClass.a_classmethod_property
600614
1 SampleClass.a_property
601615
1 SampleClass.a_staticmethod
602616
1 SampleClass.double
@@ -617,6 +631,7 @@ def basics(): r"""
617631
0 SampleClass.NestedClass.square
618632
1 SampleClass.__init__
619633
2 SampleClass.a_classmethod
634+
1 SampleClass.a_classmethod_property
620635
1 SampleClass.a_property
621636
1 SampleClass.a_staticmethod
622637
1 SampleClass.double

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1885,6 +1885,7 @@ Bob Watson
18851885
Colin Watson
18861886
David Watson
18871887
Aaron Watters
1888+
Alex Waygood
18881889
Henrik Weber
18891890
Leon Weber
18901891
Steve Weber
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix bug in the :mod:`doctest` module that caused it to fail if a docstring
2+
included an example with a ``classmethod`` ``property``. Patch by Alex
3+
Waygood.

0 commit comments

Comments
 (0)