Skip to content

Commit

Permalink
Support dataclasses (#48)
Browse files Browse the repository at this point in the history
  • Loading branch information
flying-sheep authored Mar 11, 2022
1 parent 096f533 commit d65ce60
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 28 deletions.
4 changes: 3 additions & 1 deletion scanpydoc/elegant_typehints/formatting.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def format_annotation(annotation: Type[Any], config: Config) -> Optional[str]:

curframe = inspect.currentframe()
calframe = inspect.getouterframes(curframe, 2)
if calframe[2].function == "process_docstring":
if "process_docstring" in {calframe[2].function, calframe[3].function}:
return format_both(annotation, config)
else: # recursive use
return _format_full(annotation, config)
Expand All @@ -102,6 +102,8 @@ def format_annotation(annotation: Type[Any], config: Config) -> Optional[str]:
def format_both(annotation: Type[Any], config: Config) -> str:
terse = _format_terse(annotation, config)
full = _format_full(annotation, config) or _format_orig(annotation, config)
if terse == full:
return terse
return f":annotation-terse:`{_escape(terse)}`\\ :annotation-full:`{_escape(full)}`"


Expand Down
24 changes: 21 additions & 3 deletions scanpydoc/rtd_github_links.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,21 @@
-----
You can use the filter e.g. in `autosummary templates`_.
To configure the sphinx_rtd_theme_, override the ``autosummary/base.rst`` template like this:
To configure the sphinx_rtd_theme_,
override the ``autosummary/base.rst`` template like this:
.. code:: restructuredtext
:github_url: {{ fullname | github_url }}
{% extends "!autosummary/base.rst" %}
.. _autosummary templates: http://www.sphinx-doc.org/en/master/usage/extensions/autosummary.html#customizing-templates
.. _autosummary templates: \
http://www.sphinx-doc.org/en/master/usage/extensions/autosummary.html#customizing-templates
.. _sphinx_rtd_theme: https://sphinx-rtd-theme.readthedocs.io/en/latest/
"""
from __future__ import annotations

import inspect
import sys
from pathlib import Path, PurePosixPath
Expand Down Expand Up @@ -74,7 +78,13 @@ def _get_obj_module(qualname: str) -> Tuple[Any, ModuleType]:
mod = sys.modules[modname]
obj = None
for attr_name in attr_path:
thing = getattr(mod if obj is None else obj, attr_name)
try:
thing = getattr(mod if obj is None else obj, attr_name)
except AttributeError:
if is_dataclass(obj):
thing = next(f for f in fields(obj) if f.name == attr_name)
else:
raise
if isinstance(thing, ModuleType):
mod = thing
else:
Expand Down Expand Up @@ -159,3 +169,11 @@ def setup(app: Sphinx) -> Dict[str, Any]:
DEFAULT_FILTERS["github_url"] = github_url

return metadata


if True: # test data
from dataclasses import dataclass, field, fields, is_dataclass

@dataclass
class _TestCls:
test_attr: dict[str, str] = field(default_factory=dict)
30 changes: 6 additions & 24 deletions tests/test_elegant_typehints.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,7 @@ def fn_test(s: str):
:param s: Test
"""

assert process_doc(fn_test) == [
":type s: "
r":annotation-terse:`:py:class:\`str\``\ "
r":annotation-full:`:py:class:\`str\``",
":param s: Test",
]
assert process_doc(fn_test) == [":type s: :py:class:`str`", ":param s: Test"]


def test_defaults_simple(process_doc):
Expand All @@ -97,20 +92,11 @@ def fn_test(s: str = "foo", n: None = None, i_: int = 1):
"""

assert process_doc(fn_test) == [
":type s: "
r":annotation-terse:`:py:class:\`str\``\ "
r":annotation-full:`:py:class:\`str\`` "
"(default: ``'foo'``)",
":type s: :py:class:`str` (default: ``'foo'``)",
":param s: Test S",
":type n: "
r":annotation-terse:`:py:obj:\`None\``\ "
r":annotation-full:`:py:obj:\`None\`` "
"(default: ``None``)",
":type n: :py:obj:`None` (default: ``None``)",
":param n: Test N",
r":type i\_: "
r":annotation-terse:`:py:class:\`int\``\ "
r":annotation-full:`:py:class:\`int\`` "
"(default: ``1``)",
r":type i\_: :py:class:`int` (default: ``1``)",
r":param i\_: Test I",
]

Expand Down Expand Up @@ -335,13 +321,9 @@ def fn_test():
if not re.match("^:(rtype|param|annotation-(full|terse)):", l)
]
assert lines == [
r":return: foo : "
r":annotation-terse:`:py:class:\`str\``\ "
r":annotation-full:`:py:class:\`str\``",
r":return: foo : :py:class:`str`",
" A foo!",
r" bar : "
r":annotation-terse:`:py:class:\`int\``\ "
r":annotation-full:`:py:class:\`int\``",
r" bar : :py:class:`int`",
" A bar!",
]

Expand Down
7 changes: 7 additions & 0 deletions tests/test_rtd_github_links.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import dataclasses
from dataclasses import Field, dataclass, field
from pathlib import Path

import pytest
Expand Down Expand Up @@ -30,3 +32,8 @@ def test_get_obj_module():
obj, mod = _get_obj_module("scanpydoc.get_version")
assert obj is get_version.get_version
assert mod is get_version


def test_get_obj_module_anntation():
obj, mod = _get_obj_module("scanpydoc.rtd_github_links._TestCls.test_attr")
assert isinstance(obj, Field)

0 comments on commit d65ce60

Please sign in to comment.