|
|
|
@ -1,11 +1,14 @@
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import functools
|
|
|
|
|
import pathlib
|
|
|
|
|
from typing import List, Optional
|
|
|
|
|
from typing import List, Optional, Tuple
|
|
|
|
|
|
|
|
|
|
import sphinx
|
|
|
|
|
import sphinx.util
|
|
|
|
|
import sphinx.util.logging
|
|
|
|
|
|
|
|
|
|
from ..base import PythonMapperBase
|
|
|
|
|
|
|
|
|
|
from .settings import OWN_PAGE_LEVELS
|
|
|
|
|
|
|
|
|
|
LOGGER = sphinx.util.logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
@ -27,105 +30,176 @@ def _format_args(args_info, include_annotations=True, ignore_self=None):
|
|
|
|
|
return ", ".join(result)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PythonPythonMapper(PythonMapperBase):
|
|
|
|
|
"""A base class for all types of representations of Python objects.
|
|
|
|
|
class PythonObject:
|
|
|
|
|
"""A class representing an entity from the parsed source code.
|
|
|
|
|
|
|
|
|
|
Attributes:
|
|
|
|
|
name (str): The name given to this object.
|
|
|
|
|
id (str): A unique identifier for this object.
|
|
|
|
|
children (list(PythonPythonMapper)): The members of this object.
|
|
|
|
|
This class turns the dictionaries output by the parser into an object.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
obj: JSON object representing this object
|
|
|
|
|
jinja_env: A template environment for rendering this object
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
language = "python"
|
|
|
|
|
is_callable = False
|
|
|
|
|
member_order = 0
|
|
|
|
|
"""The ordering of objects when doing "groupwise" sorting."""
|
|
|
|
|
type: str
|
|
|
|
|
|
|
|
|
|
def __init__(self, obj, class_content="class", **kwargs) -> None:
|
|
|
|
|
super().__init__(obj, **kwargs)
|
|
|
|
|
def __init__(
|
|
|
|
|
self, obj, jinja_env, app, url_root, options=None, class_content="class"
|
|
|
|
|
):
|
|
|
|
|
self.app = app
|
|
|
|
|
self.obj = obj
|
|
|
|
|
self.options = options
|
|
|
|
|
self.jinja_env = jinja_env
|
|
|
|
|
self.url_root = url_root
|
|
|
|
|
|
|
|
|
|
self.name: str = obj["name"]
|
|
|
|
|
"""The name of the object, as named in the parsed source code.
|
|
|
|
|
|
|
|
|
|
self.name = obj["name"]
|
|
|
|
|
self.qual_name = obj["qual_name"]
|
|
|
|
|
self.id = obj.get("full_name", self.name)
|
|
|
|
|
This name will have no periods in it.
|
|
|
|
|
"""
|
|
|
|
|
self.qual_name: str = obj["qual_name"]
|
|
|
|
|
"""The qualified name for this object."""
|
|
|
|
|
self.id: str = obj.get("full_name", self.name)
|
|
|
|
|
"""A globally unique identifier for this object.
|
|
|
|
|
|
|
|
|
|
This is the same as the fully qualified name of the object.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
# Optional
|
|
|
|
|
self.children: List[PythonPythonMapper] = []
|
|
|
|
|
self._docstring = obj["doc"]
|
|
|
|
|
self._docstring_resolved = False
|
|
|
|
|
self.imported = "original_path" in obj
|
|
|
|
|
self.inherited = obj.get("inherited", False)
|
|
|
|
|
"""Whether this was inherited from an ancestor of the parent class.
|
|
|
|
|
self.children: List[PythonObject] = []
|
|
|
|
|
"""The members of this object.
|
|
|
|
|
|
|
|
|
|
:type: bool
|
|
|
|
|
For example, the classes and functions defined in the parent module.
|
|
|
|
|
"""
|
|
|
|
|
self._docstring: str = obj["doc"]
|
|
|
|
|
self.imported: bool = "original_path" in obj
|
|
|
|
|
"""Whether this object was imported from another module."""
|
|
|
|
|
self.inherited: bool = obj.get("inherited", False)
|
|
|
|
|
"""Whether this was inherited from an ancestor of the parent class."""
|
|
|
|
|
self._hide = obj.get("hide", False)
|
|
|
|
|
|
|
|
|
|
# For later
|
|
|
|
|
self._class_content = class_content
|
|
|
|
|
|
|
|
|
|
self._display_cache: Optional[bool] = None
|
|
|
|
|
|
|
|
|
|
def __getstate__(self):
|
|
|
|
|
"""Obtains serialisable data for pickling."""
|
|
|
|
|
__dict__ = self.__dict__.copy()
|
|
|
|
|
__dict__.update(app=None, jinja_env=None) # clear unpickable attributes
|
|
|
|
|
return __dict__
|
|
|
|
|
|
|
|
|
|
def render(self, **kwargs):
|
|
|
|
|
LOGGER.log("VERBOSE", "Rendering %s", self.id)
|
|
|
|
|
|
|
|
|
|
template = self.jinja_env.get_template(f"python/{self.type}.rst")
|
|
|
|
|
|
|
|
|
|
ctx = {}
|
|
|
|
|
ctx.update(**self.get_context_data())
|
|
|
|
|
ctx.update(**kwargs)
|
|
|
|
|
return template.render(**ctx)
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def rendered(self):
|
|
|
|
|
"""Shortcut to render an object in templates."""
|
|
|
|
|
return self.render()
|
|
|
|
|
|
|
|
|
|
def get_context_data(self):
|
|
|
|
|
own_page_level = self.app.config.autoapi_own_page_level
|
|
|
|
|
desired_page_level = OWN_PAGE_LEVELS.index(own_page_level)
|
|
|
|
|
own_page_types = set(OWN_PAGE_LEVELS[: desired_page_level + 1])
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
"autoapi_options": self.app.config.autoapi_options,
|
|
|
|
|
"include_summaries": self.app.config.autoapi_include_summaries,
|
|
|
|
|
"obj": self,
|
|
|
|
|
"own_page_types": own_page_types,
|
|
|
|
|
"sphinx_version": sphinx.version_info,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def __lt__(self, other):
|
|
|
|
|
"""Object sorting comparison"""
|
|
|
|
|
if not isinstance(other, PythonObject):
|
|
|
|
|
return NotImplemented
|
|
|
|
|
|
|
|
|
|
return self.id < other.id
|
|
|
|
|
|
|
|
|
|
def __str__(self) -> str:
|
|
|
|
|
return f"<{self.__class__.__name__} {self.id}>"
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def short_name(self) -> str:
|
|
|
|
|
"""Shorten name property"""
|
|
|
|
|
return self.name.split(".")[-1]
|
|
|
|
|
|
|
|
|
|
def output_dir(self, root):
|
|
|
|
|
"""The directory to render this object."""
|
|
|
|
|
module = self.id[: -(len("." + self.qual_name))]
|
|
|
|
|
parts = [root] + module.split(".")
|
|
|
|
|
return pathlib.PurePosixPath(*parts)
|
|
|
|
|
|
|
|
|
|
def output_filename(self) -> str:
|
|
|
|
|
"""The name of the file to render into, without a file suffix."""
|
|
|
|
|
filename = self.qual_name
|
|
|
|
|
if filename == "index":
|
|
|
|
|
filename = ".index"
|
|
|
|
|
|
|
|
|
|
return filename
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def include_path(self) -> str:
|
|
|
|
|
"""Return 'absolute' path without regarding OS path separator
|
|
|
|
|
|
|
|
|
|
This is used in ``toctree`` directives, as Sphinx always expects Unix
|
|
|
|
|
path separators
|
|
|
|
|
"""
|
|
|
|
|
return str(self.output_dir(self.url_root) / self.output_filename())
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def docstring(self):
|
|
|
|
|
def docstring(self) -> str:
|
|
|
|
|
"""The docstring for this object.
|
|
|
|
|
|
|
|
|
|
If a docstring did not exist on the object,
|
|
|
|
|
this will be the empty string.
|
|
|
|
|
|
|
|
|
|
For classes this will also depend on the
|
|
|
|
|
For classes, this will also depend on the
|
|
|
|
|
:confval:`autoapi_python_class_content` option.
|
|
|
|
|
|
|
|
|
|
:type: str
|
|
|
|
|
"""
|
|
|
|
|
return self._docstring
|
|
|
|
|
|
|
|
|
|
@docstring.setter
|
|
|
|
|
def docstring(self, value):
|
|
|
|
|
def docstring(self, value: str) -> None:
|
|
|
|
|
self._docstring = value
|
|
|
|
|
self._docstring_resolved = True
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def is_top_level_object(self):
|
|
|
|
|
def is_top_level_object(self) -> bool:
|
|
|
|
|
"""Whether this object is at the very top level (True) or not (False).
|
|
|
|
|
|
|
|
|
|
This will be False for subpackages and submodules.
|
|
|
|
|
|
|
|
|
|
:type: bool
|
|
|
|
|
"""
|
|
|
|
|
return "." not in self.id
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def is_undoc_member(self):
|
|
|
|
|
"""Whether this object has a docstring (False) or not (True).
|
|
|
|
|
|
|
|
|
|
:type: bool
|
|
|
|
|
"""
|
|
|
|
|
def is_undoc_member(self) -> bool:
|
|
|
|
|
"""Whether this object has a docstring (False) or not (True)."""
|
|
|
|
|
return not bool(self.docstring)
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def is_private_member(self):
|
|
|
|
|
"""Whether this object is private (True) or not (False).
|
|
|
|
|
|
|
|
|
|
:type: bool
|
|
|
|
|
"""
|
|
|
|
|
def is_private_member(self) -> bool:
|
|
|
|
|
"""Whether this object is private (True) or not (False)."""
|
|
|
|
|
return self.short_name.startswith("_") and not self.short_name.endswith("__")
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def is_special_member(self):
|
|
|
|
|
"""Whether this object is a special member (True) or not (False).
|
|
|
|
|
|
|
|
|
|
:type: bool
|
|
|
|
|
"""
|
|
|
|
|
def is_special_member(self) -> bool:
|
|
|
|
|
"""Whether this object is a special member (True) or not (False)."""
|
|
|
|
|
return self.short_name.startswith("__") and self.short_name.endswith("__")
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def display(self):
|
|
|
|
|
def display(self) -> bool:
|
|
|
|
|
"""Whether this object should be displayed in documentation.
|
|
|
|
|
|
|
|
|
|
This attribute depends on the configuration options given in
|
|
|
|
|
:confval:`autoapi_options` and the result of :event:`autoapi-skip-member`.
|
|
|
|
|
|
|
|
|
|
:type: bool
|
|
|
|
|
"""
|
|
|
|
|
if self._display_cache is None:
|
|
|
|
|
self._display_cache = not self._ask_ignore(self._should_skip())
|
|
|
|
@ -133,13 +207,11 @@ class PythonPythonMapper(PythonMapperBase):
|
|
|
|
|
return self._display_cache
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def summary(self):
|
|
|
|
|
def summary(self) -> str:
|
|
|
|
|
"""The summary line of the docstring.
|
|
|
|
|
|
|
|
|
|
The summary line is the first non-empty line, as-per :pep:`257`.
|
|
|
|
|
This will be the empty string if the object does not have a docstring.
|
|
|
|
|
|
|
|
|
|
:type: str
|
|
|
|
|
"""
|
|
|
|
|
for line in self.docstring.splitlines():
|
|
|
|
|
line = line.strip()
|
|
|
|
@ -148,7 +220,7 @@ class PythonPythonMapper(PythonMapperBase):
|
|
|
|
|
|
|
|
|
|
return ""
|
|
|
|
|
|
|
|
|
|
def _should_skip(self): # type: () -> bool
|
|
|
|
|
def _should_skip(self) -> bool:
|
|
|
|
|
skip_undoc_member = self.is_undoc_member and "undoc-members" not in self.options
|
|
|
|
|
skip_private_member = (
|
|
|
|
|
self.is_private_member and "private-members" not in self.options
|
|
|
|
@ -170,61 +242,53 @@ class PythonPythonMapper(PythonMapperBase):
|
|
|
|
|
or skip_inherited_member
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def _ask_ignore(self, skip): # type: (bool) -> bool
|
|
|
|
|
def _ask_ignore(self, skip: bool) -> bool:
|
|
|
|
|
ask_result = self.app.emit_firstresult(
|
|
|
|
|
"autoapi-skip-member", self.type, self.id, self, skip, self.options
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return ask_result if ask_result is not None else skip
|
|
|
|
|
|
|
|
|
|
def _children_of_type(self, type_):
|
|
|
|
|
def _children_of_type(self, type_: str) -> List[PythonObject]:
|
|
|
|
|
return list(child for child in self.children if child.type == type_)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PythonFunction(PythonPythonMapper):
|
|
|
|
|
class PythonFunction(PythonObject):
|
|
|
|
|
"""The representation of a function."""
|
|
|
|
|
|
|
|
|
|
type = "function"
|
|
|
|
|
is_callable = True
|
|
|
|
|
member_order = 30
|
|
|
|
|
|
|
|
|
|
def __init__(self, obj, **kwargs):
|
|
|
|
|
super().__init__(obj, **kwargs)
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
super().__init__(*args, **kwargs)
|
|
|
|
|
|
|
|
|
|
autodoc_typehints = getattr(self.app.config, "autodoc_typehints", "signature")
|
|
|
|
|
show_annotations = autodoc_typehints != "none" and not (
|
|
|
|
|
autodoc_typehints == "description" and not obj["overloads"]
|
|
|
|
|
autodoc_typehints == "description" and not self.obj["overloads"]
|
|
|
|
|
)
|
|
|
|
|
self.args = _format_args(obj["args"], show_annotations)
|
|
|
|
|
"""The arguments to this object, formatted as a string.
|
|
|
|
|
self.args: str = _format_args(self.obj["args"], show_annotations)
|
|
|
|
|
"""The arguments to this object, formatted as a string."""
|
|
|
|
|
|
|
|
|
|
:type: str
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
self.return_annotation = obj["return_annotation"] if show_annotations else None
|
|
|
|
|
self.return_annotation: Optional[str] = (
|
|
|
|
|
self.obj["return_annotation"] if show_annotations else None
|
|
|
|
|
)
|
|
|
|
|
"""The type annotation for the return type of this function.
|
|
|
|
|
|
|
|
|
|
This will be ``None`` if an annotation
|
|
|
|
|
or annotation comment was not given.
|
|
|
|
|
|
|
|
|
|
:type: str or None
|
|
|
|
|
"""
|
|
|
|
|
self.properties = obj["properties"]
|
|
|
|
|
self.properties: List[str] = self.obj["properties"]
|
|
|
|
|
"""The properties that describe what type of function this is.
|
|
|
|
|
|
|
|
|
|
Can be only be: async
|
|
|
|
|
|
|
|
|
|
:type: list(str)
|
|
|
|
|
Can be only be: async.
|
|
|
|
|
"""
|
|
|
|
|
self.overloads = [
|
|
|
|
|
self.overloads: List[Tuple[str, str]] = [
|
|
|
|
|
(_format_args(args), return_annotation)
|
|
|
|
|
for args, return_annotation in obj["overloads"]
|
|
|
|
|
for args, return_annotation in self.obj["overloads"]
|
|
|
|
|
]
|
|
|
|
|
"""The overloaded signatures of this function.
|
|
|
|
|
|
|
|
|
|
Each tuple is a tuple of ``(args, return_annotation)``
|
|
|
|
|
|
|
|
|
|
:type: list(tuple(str, str))
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -232,73 +296,61 @@ class PythonMethod(PythonFunction):
|
|
|
|
|
"""The representation of a method."""
|
|
|
|
|
|
|
|
|
|
type = "method"
|
|
|
|
|
is_callable = True
|
|
|
|
|
member_order = 50
|
|
|
|
|
|
|
|
|
|
def __init__(self, obj, **kwargs):
|
|
|
|
|
super().__init__(obj, **kwargs)
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
super().__init__(*args, **kwargs)
|
|
|
|
|
|
|
|
|
|
self.properties = obj["properties"]
|
|
|
|
|
self.properties: List[str] = self.obj["properties"]
|
|
|
|
|
"""The properties that describe what type of method this is.
|
|
|
|
|
|
|
|
|
|
Can be any of: abstractmethod, async, classmethod, property, staticmethod
|
|
|
|
|
|
|
|
|
|
:type: list(str)
|
|
|
|
|
Can be any of: abstractmethod, async, classmethod, property, staticmethod.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def _should_skip(self): # type: () -> bool
|
|
|
|
|
def _should_skip(self) -> bool:
|
|
|
|
|
return super()._should_skip() or self.name in (
|
|
|
|
|
"__new__",
|
|
|
|
|
"__init__",
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PythonProperty(PythonPythonMapper):
|
|
|
|
|
class PythonProperty(PythonObject):
|
|
|
|
|
"""The representation of a property on a class."""
|
|
|
|
|
|
|
|
|
|
type = "property"
|
|
|
|
|
member_order = 60
|
|
|
|
|
|
|
|
|
|
def __init__(self, obj, **kwargs):
|
|
|
|
|
super().__init__(obj, **kwargs)
|
|
|
|
|
|
|
|
|
|
self.annotation = obj["return_annotation"]
|
|
|
|
|
"""The type annotation of this property.
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
super().__init__(*args, **kwargs)
|
|
|
|
|
|
|
|
|
|
:type: str or None
|
|
|
|
|
"""
|
|
|
|
|
self.properties = obj["properties"]
|
|
|
|
|
self.annotation: Optional[str] = self.obj["return_annotation"]
|
|
|
|
|
"""The type annotation of this property."""
|
|
|
|
|
self.properties: List[str] = self.obj["properties"]
|
|
|
|
|
"""The properties that describe what type of property this is.
|
|
|
|
|
|
|
|
|
|
Can be any of: abstractmethod, classmethod
|
|
|
|
|
|
|
|
|
|
:type: list(str)
|
|
|
|
|
Can be any of: abstractmethod, classmethod.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PythonData(PythonPythonMapper):
|
|
|
|
|
class PythonData(PythonObject):
|
|
|
|
|
"""Global, module level data."""
|
|
|
|
|
|
|
|
|
|
type = "data"
|
|
|
|
|
member_order = 40
|
|
|
|
|
|
|
|
|
|
def __init__(self, obj, **kwargs):
|
|
|
|
|
super().__init__(obj, **kwargs)
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
super().__init__(*args, **kwargs)
|
|
|
|
|
|
|
|
|
|
self.value = obj.get("value")
|
|
|
|
|
self.value: Optional[str] = self.obj.get("value")
|
|
|
|
|
"""The value of this attribute.
|
|
|
|
|
|
|
|
|
|
This will be ``None`` if the value is not constant.
|
|
|
|
|
|
|
|
|
|
:type: str or None
|
|
|
|
|
"""
|
|
|
|
|
self.annotation = obj.get("annotation")
|
|
|
|
|
self.annotation: Optional[str] = self.obj.get("annotation")
|
|
|
|
|
"""The type annotation of this attribute.
|
|
|
|
|
|
|
|
|
|
This will be ``None`` if an annotation
|
|
|
|
|
or annotation comment was not given.
|
|
|
|
|
|
|
|
|
|
:type: str or None
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -309,17 +361,15 @@ class PythonAttribute(PythonData):
|
|
|
|
|
member_order = 60
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TopLevelPythonPythonMapper(PythonPythonMapper):
|
|
|
|
|
class TopLevelPythonPythonMapper(PythonObject):
|
|
|
|
|
"""A common base class for modules and packages."""
|
|
|
|
|
|
|
|
|
|
_RENDER_LOG_LEVEL = "VERBOSE"
|
|
|
|
|
|
|
|
|
|
def __init__(self, obj, **kwargs):
|
|
|
|
|
super().__init__(obj, **kwargs)
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
super().__init__(*args, **kwargs)
|
|
|
|
|
|
|
|
|
|
self.subpackages = []
|
|
|
|
|
self.submodules = []
|
|
|
|
|
self.all = obj["all"]
|
|
|
|
|
self.all = self.obj["all"]
|
|
|
|
|
"""The contents of ``__all__`` if assigned to.
|
|
|
|
|
|
|
|
|
|
Only constants are included.
|
|
|
|
@ -366,27 +416,23 @@ class PythonPackage(TopLevelPythonPythonMapper):
|
|
|
|
|
type = "package"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PythonClass(PythonPythonMapper):
|
|
|
|
|
class PythonClass(PythonObject):
|
|
|
|
|
"""The representation of a class."""
|
|
|
|
|
|
|
|
|
|
type = "class"
|
|
|
|
|
member_order = 20
|
|
|
|
|
|
|
|
|
|
def __init__(self, obj, **kwargs):
|
|
|
|
|
super().__init__(obj, **kwargs)
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
super().__init__(*args, **kwargs)
|
|
|
|
|
|
|
|
|
|
self.bases = obj["bases"]
|
|
|
|
|
"""The fully qualified names of all base classes.
|
|
|
|
|
self.bases: List[str] = self.obj["bases"]
|
|
|
|
|
"""The fully qualified names of all base classes."""
|
|
|
|
|
|
|
|
|
|
:type: list(str)
|
|
|
|
|
"""
|
|
|
|
|
self._docstring_resolved: bool = False
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def args(self):
|
|
|
|
|
"""The arguments to this object, formatted as a string.
|
|
|
|
|
|
|
|
|
|
:type: str
|
|
|
|
|
"""
|
|
|
|
|
def args(self) -> str:
|
|
|
|
|
"""The arguments to this object, formatted as a string."""
|
|
|
|
|
args = ""
|
|
|
|
|
|
|
|
|
|
if self.constructor:
|
|
|
|
@ -402,7 +448,7 @@ class PythonClass(PythonPythonMapper):
|
|
|
|
|
return args
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def overloads(self):
|
|
|
|
|
def overloads(self) -> List[Tuple[str, str]]:
|
|
|
|
|
overloads = []
|
|
|
|
|
|
|
|
|
|
if self.constructor:
|
|
|
|
@ -422,8 +468,8 @@ class PythonClass(PythonPythonMapper):
|
|
|
|
|
return overloads
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def docstring(self):
|
|
|
|
|
docstring = super().docstring
|
|
|
|
|
def docstring(self) -> str:
|
|
|
|
|
docstring = self._docstring
|
|
|
|
|
|
|
|
|
|
if not self._docstring_resolved and self._class_content in ("both", "init"):
|
|
|
|
|
constructor_docstring = self.constructor_docstring
|
|
|
|
@ -437,8 +483,9 @@ class PythonClass(PythonPythonMapper):
|
|
|
|
|
return docstring
|
|
|
|
|
|
|
|
|
|
@docstring.setter
|
|
|
|
|
def docstring(self, value):
|
|
|
|
|
super(PythonClass, self.__class__).docstring.fset(self, value)
|
|
|
|
|
def docstring(self, value: str) -> None:
|
|
|
|
|
self._docstring = value
|
|
|
|
|
self._docstring_resolved = True
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def methods(self):
|
|
|
|
@ -466,7 +513,7 @@ class PythonClass(PythonPythonMapper):
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def constructor_docstring(self):
|
|
|
|
|
def constructor_docstring(self) -> str:
|
|
|
|
|
docstring = ""
|
|
|
|
|
|
|
|
|
|
constructor = self.constructor
|