Skip to content

Commit

Permalink
feat: Load docstrings and functions arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
pawamoy committed Sep 15, 2021
1 parent 8f4df75 commit cdf29a3
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 14 deletions.
149 changes: 136 additions & 13 deletions src/griffe/dataclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,89 @@
from __future__ import annotations

import enum
import inspect
from pathlib import Path
from typing import Any

ParameterKind = inspect._ParameterKind # noqa: WPS437


class Docstring:
"""This class represents docstrings.
Attributes:
value: The actual documentation string, cleaned up.
lineno: The starting line number.
endlineno: The ending line number.
"""

def __init__(self, value: str, lineno: int | None, endlineno: int | None) -> None:
"""Initialize the docstring.
Arguments:
value: The docstring value.
lineno: The starting line number.
endlineno: The ending line number.
"""
self.value: str = inspect.cleandoc(value)
self.lineno: int | None = lineno
self.endlineno: int | None = endlineno

def as_dict(self, full=False) -> dict[str, Any]:
"""Return this docstring's data as a dictionary.
Arguments:
full: Whether to return full info, or just base info.
Returns:
A dictionary.
"""
return {
"value": self.value,
"lineno": self.lineno,
"endlineno": self.endlineno,
}


class Argument:
"""This class represent a function argument.
Attributes:
name: The argument name.
annotation: The argument annotation, if any.
kind: The argument kind (see [`inspect.Parameter.kind`][]).
default: The argument default, if any.
"""

def __init__(self, name: str, annotation: str | None, kind: ParameterKind, default: str | None) -> None:
"""Initialize the argument.
Arguments:
name: The argument name.
annotation: The argument annotation, if any.
kind: The argument kind (see [`inspect.Parameter.kind`][]).
default: The argument default, if any.
"""
self.name: str = name
self.annotation: str | None = annotation
self.kind: ParameterKind = kind
self.default: str | None = default

def as_dict(self, full=False) -> dict[str, Any]:
"""Return this argument's data as a dictionary.
Arguments:
full: Whether to return full info, or just base info.
Returns:
A dictionary.
"""
return {
"name": self.name,
"annotation": self.annotation,
"kind": self.kind,
"default": self.default,
}


class Kind(enum.Enum):
Expand All @@ -32,26 +114,35 @@ class Object:
Attributes:
kind: The object kind.
name: The object name.
lineno: The object starting line, or None for modules. Lines start at 1..
endlineno: The object ending line (inclusive), or None for modules..
lineno: The object starting line, or None for modules. Lines start at 1.
endlineno: The object ending line (inclusive), or None for modules.
docstring: The object docstring.
parent: The object parent, or None if it is the top module.
members: The object members.
labels: The object labels.
"""

kind: Kind

def __init__(self, name: str, lineno: int | None = None, endlineno: int | None = None) -> None:
def __init__(
self,
name: str,
lineno: int | None = None,
endlineno: int | None = None,
docstring: Docstring | None = None,
) -> None:
"""Initialize the object.
Arguments:
name: The object name, as declared in the code.
lineno: The object starting line, or None for modules. Lines start at 1.
endlineno: The object ending line (inclusive), or None for modules.
docstring: The object docstring.
"""
self.name: str = name
self.lineno: int | None = lineno
self.endlineno: int | None = endlineno
self.docstring: Docstring | None = docstring
self.parent: Module | Class | None = None
self.members: dict[str, Module | Class | Function | Data] = {}
self.labels: set[str] = set()
Expand Down Expand Up @@ -128,7 +219,7 @@ def path(self) -> str:
return self.name
return ".".join((self.parent.path, self.name))

def as_dict(self, full: bool = False) -> dict:
def as_dict(self, full: bool = False) -> dict[str, Any]:
"""Return this object's data as a dictionary.
Arguments:
Expand All @@ -138,24 +229,29 @@ def as_dict(self, full: bool = False) -> dict:
A dictionary.
"""
base = {
"name": self.name,
"members": [member.as_dict(full) for member in self.members.values()],
"labels": self.labels,
"kind": self.kind,
"name": self.name,
}
if self.lineno:
base["lineno"] = self.lineno
if self.endlineno:
base["endlineno"] = self.endlineno

if full:
base.update(
{
"filepath": str(self.filepath),
"path": self.path,
"filepath": str(self.filepath),
}
)

if self.lineno:
base["lineno"] = self.lineno
if self.endlineno:
base["endlineno"] = self.endlineno
if self.docstring:
base["docstring"] = self.docstring

# doing this last for a prettier JSON dump
base["labels"] = self.labels
base["members"] = [member.as_dict(full) for member in self.members.values()]

return base


Expand Down Expand Up @@ -246,7 +342,7 @@ def is_namespace_subpackage(self) -> bool:
or self.parent.is_namespace_package # type: ignore # modules parents are always modules
)

def as_dict(self, full: bool = False) -> dict:
def as_dict(self, full: bool = False) -> dict[str, Any]:
"""Return this module's data as a dictionary.
Arguments:
Expand All @@ -271,6 +367,33 @@ class Function(Object):

kind = Kind.FUNCTION

def __init__(self, *args, arguments: list[Argument] | None = None, returns: str | None = None, **kwargs) -> None:
"""Initialize the module.
Arguments:
*args: See [`griffe.dataclasses.Object`][].
arguments: The function arguments.
returns: The function return annotation.
**kwargs: See [`griffe.dataclasses.Object`][].
"""
super().__init__(*args, **kwargs)
self.arguments = arguments or []
self.returns = returns

def as_dict(self, full: bool = False) -> dict[str, Any]:
"""Return this function's data as a dictionary.
Arguments:
full: Whether to return full info, or just base info.
Returns:
A dictionary.
"""
base = super().as_dict(full=full)
base["arguments"] = [arg.as_dict(full=full) for arg in self.arguments]
base["returns"] = self.returns
return base


class Data(Object):
"""The class representing a Python module/class/instance attribute."""
Expand Down
4 changes: 3 additions & 1 deletion src/griffe/encoders.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from pathlib import Path
from typing import Any

from griffe.dataclasses import Class, Data, Function, Kind, Module
from griffe.dataclasses import Class, Data, Function, Kind, Module, ParameterKind


class Encoder(json.JSONEncoder):
Expand Down Expand Up @@ -53,6 +53,8 @@ def default(self, obj: Any) -> Any:
"""
if hasattr(obj, "as_dict"):
return obj.as_dict(self.full)
if isinstance(obj, ParameterKind):
return str(ParameterKind)
if isinstance(obj, Kind):
return obj.value
if isinstance(obj, set):
Expand Down

0 comments on commit cdf29a3

Please sign in to comment.