23
23
from itertools import tee , groupby
24
24
from types import ModuleType
25
25
from typing import ( # noqa: F401
26
- cast , Any , Callable , Dict , Generator , Iterable , List , Mapping , NewType ,
26
+ cast , Any , Callable , Dict , Generator , Iterable , List , Literal , Mapping , NewType ,
27
27
Optional , Set , Tuple , Type , TypeVar , Union ,
28
28
)
29
29
from unittest .mock import Mock
@@ -421,6 +421,14 @@ def _is_descriptor(obj):
421
421
inspect .ismemberdescriptor (obj ))
422
422
423
423
424
+ def _unwrap_descriptor (obj ):
425
+ if isinstance (obj , property ):
426
+ return (getattr (obj , 'fget' , False ) or
427
+ getattr (obj , 'fset' , False ) or
428
+ getattr (obj , 'fdel' , obj ))
429
+ return getattr (obj , '__get__' , obj )
430
+
431
+
424
432
def _filter_type (type : Type [T ],
425
433
values : Union [Iterable ['Doc' ], Mapping [str , 'Doc' ]]) -> List [T ]:
426
434
"""
@@ -542,7 +550,7 @@ def source(self) -> str:
542
550
available, an empty string.
543
551
"""
544
552
try :
545
- lines , _ = inspect .getsourcelines (self .obj )
553
+ lines , _ = inspect .getsourcelines (_unwrap_descriptor ( self .obj ) )
546
554
except (ValueError , TypeError , OSError ):
547
555
return ''
548
556
return inspect .cleandoc ('' .join (['\n ' ] + lines ))
@@ -1079,7 +1087,8 @@ def definition_order_index(
1079
1087
var_docstrings .get (name ) or
1080
1088
(inspect .isclass (obj ) or _is_descriptor (obj )) and inspect .getdoc (obj )),
1081
1089
cls = self ,
1082
- obj = getattr (obj , 'fget' , getattr (obj , '__get__' , None )),
1090
+ kind = "prop" if isinstance (obj , property ) else "var" ,
1091
+ obj = _is_descriptor (obj ) and obj or None ,
1083
1092
instance_var = (_is_descriptor (obj ) or
1084
1093
name in getattr (self .obj , '__slots__' , ())))
1085
1094
@@ -1392,7 +1401,8 @@ def return_annotation(self, *, link=None) -> str:
1392
1401
lambda : _get_type_hints (cast (Class , self .cls ).obj )[self .name ],
1393
1402
# global variables
1394
1403
lambda : _get_type_hints (not self .cls and self .module .obj )[self .name ],
1395
- lambda : inspect .signature (self .obj ).return_annotation ,
1404
+ # properties
1405
+ lambda : inspect .signature (_unwrap_descriptor (self .obj )).return_annotation ,
1396
1406
# Use raw annotation strings in unmatched forward declarations
1397
1407
lambda : cast (Class , self .cls ).obj .__annotations__ [self .name ],
1398
1408
# Extract annotation from the docstring for C builtin function
@@ -1593,10 +1603,11 @@ class Variable(Doc):
1593
1603
Representation of a variable's documentation. This includes
1594
1604
module, class, and instance variables.
1595
1605
"""
1596
- __slots__ = ('cls' , 'instance_var' )
1606
+ __slots__ = ('cls' , 'instance_var' , 'kind' )
1597
1607
1598
1608
def __init__ (self , name : str , module : Module , docstring , * ,
1599
- obj = None , cls : Optional [Class ] = None , instance_var : bool = False ):
1609
+ obj = None , cls : Optional [Class ] = None , instance_var : bool = False ,
1610
+ kind : Literal ["prop" , "var" ] = 'var' ):
1600
1611
"""
1601
1612
Same as `pdoc.Doc`, except `cls` should be provided
1602
1613
as a `pdoc.Class` object when this is a class or instance
@@ -1616,6 +1627,12 @@ def __init__(self, name: str, module: Module, docstring, *,
1616
1627
opposed to class variable).
1617
1628
"""
1618
1629
1630
+ self .kind = kind
1631
+ """
1632
+ `prop` if variable is a dynamic property (has getter/setter or deleter),
1633
+ or `var` otherwise.
1634
+ """
1635
+
1619
1636
@property
1620
1637
def qualname (self ) -> str :
1621
1638
if self .cls :
0 commit comments