Skip to content

Commit

Permalink
ENH: Discern properties from variables (#277)
Browse files Browse the repository at this point in the history
* Possible way to address issue 276.
This shows "property" if a variable is a property with a setter
and/or a deleter and "ro-property" (read only property) if it is a property which
does not have either a setter or getter.

* Shorten comment line

* Rename "vartype" to "kind".
Also make property now show get/set/del depending on what
is defined, e.g. propert/get/set

* Remove unnecessary comment.

* Make linter happy about line length.

* REF: Make pdoc.Doc.obj point to raw property/descriptor

* ENH: Introduce `Variable.kind: Literal["var","prop"]`
  • Loading branch information
johann-petrak authored Jun 22, 2024
1 parent c3fb554 commit 9b64f7f
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 7 deletions.
29 changes: 23 additions & 6 deletions pdoc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from itertools import tee, groupby
from types import ModuleType
from typing import ( # noqa: F401
cast, Any, Callable, Dict, Generator, Iterable, List, Mapping, NewType,
cast, Any, Callable, Dict, Generator, Iterable, List, Literal, Mapping, NewType,
Optional, Set, Tuple, Type, TypeVar, Union,
)
from unittest.mock import Mock
Expand Down Expand Up @@ -421,6 +421,14 @@ def _is_descriptor(obj):
inspect.ismemberdescriptor(obj))


def _unwrap_descriptor(obj):
if isinstance(obj, property):
return (getattr(obj, 'fget', False) or
getattr(obj, 'fset', False) or
getattr(obj, 'fdel', obj))
return getattr(obj, '__get__', obj)


def _filter_type(type: Type[T],
values: Union[Iterable['Doc'], Mapping[str, 'Doc']]) -> List[T]:
"""
Expand Down Expand Up @@ -542,7 +550,7 @@ def source(self) -> str:
available, an empty string.
"""
try:
lines, _ = inspect.getsourcelines(self.obj)
lines, _ = inspect.getsourcelines(_unwrap_descriptor(self.obj))
except (ValueError, TypeError, OSError):
return ''
return inspect.cleandoc(''.join(['\n'] + lines))
Expand Down Expand Up @@ -1079,7 +1087,8 @@ def definition_order_index(
var_docstrings.get(name) or
(inspect.isclass(obj) or _is_descriptor(obj)) and inspect.getdoc(obj)),
cls=self,
obj=getattr(obj, 'fget', getattr(obj, '__get__', None)),
kind="prop" if isinstance(obj, property) else "var",
obj=_is_descriptor(obj) and obj or None,
instance_var=(_is_descriptor(obj) or
name in getattr(self.obj, '__slots__', ())))

Expand Down Expand Up @@ -1392,7 +1401,8 @@ def return_annotation(self, *, link=None) -> str:
lambda: _get_type_hints(cast(Class, self.cls).obj)[self.name],
# global variables
lambda: _get_type_hints(not self.cls and self.module.obj)[self.name],
lambda: inspect.signature(self.obj).return_annotation,
# properties
lambda: inspect.signature(_unwrap_descriptor(self.obj)).return_annotation,
# Use raw annotation strings in unmatched forward declarations
lambda: cast(Class, self.cls).obj.__annotations__[self.name],
# Extract annotation from the docstring for C builtin function
Expand Down Expand Up @@ -1593,10 +1603,11 @@ class Variable(Doc):
Representation of a variable's documentation. This includes
module, class, and instance variables.
"""
__slots__ = ('cls', 'instance_var')
__slots__ = ('cls', 'instance_var', 'kind')

def __init__(self, name: str, module: Module, docstring, *,
obj=None, cls: Optional[Class] = None, instance_var: bool = False):
obj=None, cls: Optional[Class] = None, instance_var: bool = False,
kind: Literal["prop", "var"] = 'var'):
"""
Same as `pdoc.Doc`, except `cls` should be provided
as a `pdoc.Class` object when this is a class or instance
Expand All @@ -1616,6 +1627,12 @@ def __init__(self, name: str, module: Module, docstring, *,
opposed to class variable).
"""

self.kind = kind
"""
`prop` if variable is a dynamic property (has getter/setter or deleter),
or `var` otherwise.
"""

@property
def qualname(self) -> str:
if self.cls:
Expand Down
2 changes: 1 addition & 1 deletion pdoc/templates/html.mako
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@
<dl>
% for v in inst_vars:
<% return_type = get_annotation(v.type_annotation) %>
<dt id="${v.refname}"><code class="name">var ${ident(v.name)}${return_type}</code></dt>
<dt id="${v.refname}"><code class="name">${v.kind} ${ident(v.name)}${return_type}</code></dt>
<dd>${show_desc(v)}</dd>
% endfor
</dl>
Expand Down

0 comments on commit 9b64f7f

Please sign in to comment.