Skip to content

Commit

Permalink
Simplifications
Browse files Browse the repository at this point in the history
  • Loading branch information
tristanlatr committed Dec 5, 2024
1 parent 05b5618 commit 30cdb7a
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 36 deletions.
23 changes: 5 additions & 18 deletions pydoctor/epydoc/markup/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,6 @@
from importlib import import_module
from inspect import getmodulename

if sys.version_info >= (3,11):
from enum import StrEnum
else:
from enum import Enum
class StrEnum(str, Enum):
...

from docutils import nodes
from twisted.web.template import Tag, tags

Expand All @@ -64,7 +57,7 @@ class StrEnum(str, Enum):
if TYPE_CHECKING:
from twisted.web.template import Flattenable
from pydoctor.model import Documentable
from typing import Protocol
from typing import Protocol, Literal, TypeAlias
else:
Protocol = object

Expand All @@ -78,16 +71,10 @@ class StrEnum(str, Enum):
# 4. ParseError exceptions
#

class ObjClass(StrEnum):
"""
A simpler version of L{DocumentableKind} used for docstring parsing only.
Names should strictly follow L{Documentable} concrete subtypes names.
"""
Module = 'module'
Package = Module
Class = 'class'
Function = 'function'
Attribute = 'attribute'
ObjClass: TypeAlias = "Literal['module', 'class', 'function', 'attribute']"
"""
A simpler version of L{DocumentableKind} used for docstring parsing only.
"""

ParserFunction = Callable[[str, List['ParseError']], 'ParsedDocstring']

Expand Down
17 changes: 10 additions & 7 deletions pydoctor/epydoc2stan.py
Original file line number Diff line number Diff line change
Expand Up @@ -584,13 +584,16 @@ def reportErrors(obj: model.Documentable, errs: Sequence[ParseError], section:st
)

def _objclass_for_docstring_parsing(obj: model.Documentable) -> ObjClass | None:
"""
This relies on the fact that L{Documentable} class name are matching enum members in L{ObjClass}.
"""
try:
return ObjClass[type(obj).__name__]
except KeyError:
return None
# There is only 4 main kinds of objects
if isinstance(obj, model.Module):
return 'module'
if isinstance(obj, model.Class):
return 'class'
if isinstance(obj, model.Attribute):
return 'attribute'
if isinstance(obj, model.Function):
return 'function'
return None

Check warning on line 596 in pydoctor/epydoc2stan.py

View check run for this annotation

Codecov / codecov/patch

pydoctor/epydoc2stan.py#L596

Added line #L596 was not covered by tests

_docformat_skip_processtypes = ('google', 'numpy', 'plaintext')
def parse_docstring(
Expand Down
36 changes: 35 additions & 1 deletion pydoctor/test/epydoc/test_google_numpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from pydoctor.epydoc.markup import ParseError
from unittest import TestCase
from pydoctor.test import NotFoundLinker
from pydoctor.model import Attribute, System, Function
from pydoctor.model import Attribute, Class, Module, System, Function
from pydoctor.stanutils import flatten
from pydoctor.epydoc2stan import _objclass_for_docstring_parsing
from pydoctor.epydoc.markup.google import get_parser as get_google_parser
Expand Down Expand Up @@ -80,6 +80,40 @@ def test_get_numpy_parser_not_attribute(self) -> None:
assert not parse_docstring(docstring, errors).fields


def test_get_parser_for_modules_does_not_generates_ivar(self) -> None:

obj = Module(system = System(), name='thing')

parse_docstring = get_google_parser(_objclass_for_docstring_parsing(obj))

docstring = """\
Attributes:
i: struff
j: thing
"""

errors: List[ParseError] = []
parsed_doc = parse_docstring(docstring, errors)
fields_names = [f.tag() for f in parsed_doc.fields]
assert fields_names == ['var', 'var']

def test_get_parser_for_classes_generates_ivar(self) -> None:

obj = Class(system = System(), name='thing')

parse_docstring = get_google_parser(_objclass_for_docstring_parsing(obj))

docstring = """\
Attributes:
i: struff
j: thing
"""

errors: List[ParseError] = []
parsed_doc = parse_docstring(docstring, errors)
fields_names = [f.tag() for f in parsed_doc.fields]
assert fields_names == ['ivar', 'ivar']

class TestWarnings(TestCase):

def test_warnings(self) -> None:
Expand Down
20 changes: 10 additions & 10 deletions pydoctor/test/test_napoleon_docstring.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ def test_class_data_member(self):
data member description:
- a: b
"""
actual = str(GoogleDocstring(docstring, what=ObjClass.Attribute))
actual = str(GoogleDocstring(docstring, what='attribute'))
expected = """\
data member description:
- a: b"""
Expand All @@ -342,12 +342,12 @@ def test_attribute_colon_description(self):
But still, it feels a bit off.
"""
docstring = """:Returns one of: ``"Yes"`` or ``No``."""
actual = str(GoogleDocstring(docstring, what=ObjClass.Attribute))
actual = str(GoogleDocstring(docstring, what='attribute'))
expected = """Returns one of: ``"Yes"`` or ``No``."""
self.assertEqual(expected.rstrip(), actual)

docstring = """Returns one of: ``"Yes"`` or ``No``."""
actual = str(GoogleDocstring(docstring, what=ObjClass.Attribute))
actual = str(GoogleDocstring(docstring, what='attribute'))
expected = """``"Yes"`` or ``No``.\n\n:type: Returns one of"""
self.assertEqual(expected.rstrip(), actual)

Expand All @@ -358,7 +358,7 @@ def test_class_data_member_inline(self):
'a :ref:`reference`, '
'a `link <https://foo.bar>`_, '
'an host:port and HH:MM strings.')
actual = str(GoogleDocstring(docstring, what=ObjClass.Attribute))
actual = str(GoogleDocstring(docstring, what='attribute'))
expected = ("""\
data member description with :ref:`reference` inline description with ``a : in code``, a :ref:`reference`, a `link <https://foo.bar>`_, an host:port and HH:MM strings.
Expand All @@ -367,14 +367,14 @@ def test_class_data_member_inline(self):

def test_class_data_member_inline_no_type(self):
docstring = """data with ``a : in code`` and :ref:`reference` and no type"""
actual = str(GoogleDocstring(docstring, what=ObjClass.Attribute))
actual = str(GoogleDocstring(docstring, what='attribute'))
expected = """data with ``a : in code`` and :ref:`reference` and no type"""

self.assertEqual(expected.rstrip(), actual)

def test_class_data_member_inline_ref_in_type(self):
docstring = """:class:`int`: data member description"""
actual = str(GoogleDocstring(docstring, what=ObjClass.Attribute))
actual = str(GoogleDocstring(docstring, what='attribute'))
expected = ("""\
data member description
Expand All @@ -390,7 +390,7 @@ def test_attributes_in_module(self):
in_attr: super-dooper attribute
"""

actual = str(GoogleDocstring(docstring, what=ObjClass.Module))
actual = str(GoogleDocstring(docstring, what='module'))
expected = """\
:var in_attr: super-dooper attribute
"""
Expand All @@ -402,7 +402,7 @@ def test_attributes_in_class(self):
in_attr: super-dooper attribute
"""

actual = str(GoogleDocstring(docstring, what=ObjClass.Class))
actual = str(GoogleDocstring(docstring, what='class'))
expected = """\
:ivar in_attr: super-dooper attribute
"""
Expand Down Expand Up @@ -1463,7 +1463,7 @@ def test_column_summary_lines_sphinx_issue_4016(self):
self.assertAlmostEqualSphinxDocstring(expected, docstring,
type_=SphinxGoogleDocstring)

actual = str(GoogleDocstring(docstring, what=ObjClass.Attribute))
actual = str(GoogleDocstring(docstring, what='attribute'))
self.assertEqual(expected.rstrip(), actual)

docstring2 = """Put *key* and *value* into a dictionary.
Expand All @@ -1481,7 +1481,7 @@ def test_column_summary_lines_sphinx_issue_4016(self):
self.assertAlmostEqualSphinxDocstring(expected2, docstring2,
type_=SphinxGoogleDocstring)

actual = str(GoogleDocstring(docstring2, what=ObjClass.Attribute))
actual = str(GoogleDocstring(docstring2, what='attribute'))
self.assertEqual(expected2.rstrip(), actual)

def test_multiline_types(self):
Expand Down

0 comments on commit 30cdb7a

Please sign in to comment.