示例#1
0
    def __post_init__(self):
        super().__post_init__()

        members = self.members
        if self.object.kind in ["class", "dataclass"] and not self.docstring:
            for member in members:
                if member.object.name == "__init__" and member.docstring:
                    markdown = member.docstring.sections[0].markdown
                    if not markdown.startswith("Initialize self"):
                        self.docstring = member.docstring
        self.members = [m for m in members if m.object.name != "__init__"]

        doc = self.docstring
        if doc and "property" in self.object.kind:
            if not doc.type and len(doc.sections) == 1 and doc.sections[0].name == "":
                section = doc.sections[0]
                markdown = section.markdown
                type, markdown = preprocess.split_type(markdown)
                if type:
                    doc.type = Type(type)
                    section.markdown = markdown

        if doc and doc.type:
            self.object.type = doc.type
            doc.type = Type()
示例#2
0
def parse_attribute(doc: Docstring, obj: Any):
    """Parses attributes' docstring to inspect type and description from source."""
    signature = get_signature(obj)
    attrs = signature.attributes
    attrs_desc = signature.attributes_desc
    if inspect.ismethod(obj):
        print(obj)
        print(attrs)

    if not attrs:
        return
    section = doc["Attributes"]
    if section is None:
        if any(x for x in attrs_desc.values()):
            section = Section("Attributes")
            doc["Attributes"] = section
        else:
            return
    items = []
    for name in attrs:
        item = section[name]
        if item:
            if not item.type.markdown:
                item.type = Type(attrs[name])
            if not item.markdown:
                item.markdown = attrs_desc[name]
            del section[name]
        elif attrs_desc[name]:
            item = Item(name, attrs_desc[name], type=Type(attrs[name]))
        else:
            continue
        items.append(item)
    items.extend(section.items)
    section.items = items
示例#3
0
def postprocess(doc: Docstring, obj: Any):
    parse_bases(doc, obj)
    if inspect.ismodule(obj) or inspect.isclass(obj):
        parse_attribute(doc, obj)
    if isinstance(obj, property):
        parse_property(doc, obj)

    if not callable(obj):
        return

    signature = get_signature(obj)
    if signature.signature is None:
        return

    def get_type(type: str) -> Type:
        if type.startswith("("):  # tuple
            type = type[1:-1]
        return Type(type)

    if doc["Parameters"] is not None:
        for item in doc["Parameters"].items:
            if not item.type and item.name in signature.parameters:
                item.type = get_type(signature.parameters[item.name])
            if "{default}" in item.desc.markdown and item.name in signature:
                default = signature.defaults[item.name]
                item.desc.markdown = item.desc.markdown.replace(
                    "{default}", default)

    if doc["Attributes"] is not None and signature.attributes:
        for item in doc["Attributes"].items:
            if not item.type and item.name in signature.attributes:
                item.type = get_type(signature.attributes[item.name])

    for name in ["Returns", "Yields"]:
        section = doc[name]
        if section is not None and not section.type:
            section.type = Type(getattr(signature, name.lower()))

    if doc["Returns"] is None and doc["Yields"] is None:
        from mkapi.core.node import get_kind

        kind = get_kind(obj)
        if kind == "generator":
            doc.type = Type(signature.yields)
        else:
            doc.type = Type(signature.returns)

    for section in doc.sections:
        if section.name in ["Example", "Examples"]:
            break
        if section.markdown:
            section.markdown = replace_link(obj, section.markdown)
        else:
            for item in section.items:
                if item.markdown:
                    item.markdown = replace_link(obj, item.markdown)
示例#4
0
def parse_property(doc: Docstring, obj: Any):
    """Parses property's docstring to inspect type."""
    doc.type = Type(get_signature(obj.fget).returns)
    if not doc.type:
        section = doc.sections[0]
        markdown = section.markdown
        type, markdown = preprocess.split_type(markdown)
        if type:
            doc.type = Type(type)
            section.markdown = markdown
示例#5
0
def get_section(name: str, doc: str, style: str) -> Section:
    """Returns a [Section]() instance."""
    type = ""
    markdown = ""
    items = []
    if name in ["Parameters", "Attributes", "Raises"]:
        items = [
            Item(n, m, Type(t)) for n, m, t in parse_parameters(doc, style)
        ]
    elif name in ["Returns", "Yields"]:
        markdown, type = parse_returns(doc, style)
    else:
        markdown = doc
    return Section(name, markdown, items, Type(type))
示例#6
0
def postprocess(doc: Docstring, obj: Any):
    parse_bases(doc, obj)
    parse_source(doc, obj)
    if not callable(obj):
        return

    signature = get_signature(obj)
    if signature.signature is None:
        return

    if "Parameters" in doc:
        for item in doc["Parameters"].items:
            description = item.description
            if "{default}" in description.name and item.name in signature:
                default = signature.defaults[item.name]
                description.markdown = description.name.replace(
                    "{default}", default)

    for name in ["Returns", "Yields"]:
        if name in doc:
            section = doc[name]
            if not section.type:
                section.type = Type(getattr(signature, name.lower()))

    if "Returns" not in doc and "Yields" not in doc:
        from mkapi.core.node import get_kind

        kind = get_kind(obj)
        if kind == "generator":
            doc.type = Type(signature.yields)
        else:
            doc.type = Type(signature.returns)

    sections: List[Section] = []
    for section in doc.sections:
        if section.name not in ["Example", "Examples"]:
            for base in section:
                base.markdown = replace_link(obj, base.markdown)
        if section.name in ["Note", "Notes", "Warning", "Warnings"]:
            markdown = preprocess.admonition(section.name, section.markdown)
            if sections and sections[-1].name == "":
                sections[-1].markdown += "\n\n" + markdown
                continue
            else:
                section.name = ""
                section.markdown = markdown
        sections.append(section)
    doc.sections = sections
示例#7
0
def parse_parameter(lines: List[str], style: str) -> Item:
    """Returns a Item instance that represents a parameter.

    Args:
        lines: Splitted parameter docstring lines.
        style: Docstring style. `google` or `numpy`.
    """
    if style == "google":
        name, _, line = lines[0].partition(":")
        name = name.strip()
        parsed = [line.strip()]
        pattern = r"(.*?)\s*?\((.*?)\)"
    else:
        name = lines[0].strip()
        parsed = []
        pattern = r"([^ ]*?)\s*:\s*(.*)"
    if len(lines) > 1:
        indent = get_indent(lines[1])
        for line in lines[1:]:
            parsed.append(line[indent:])
    m = re.match(pattern, name)
    if m:
        name, type = m.group(1), m.group(2)
    else:
        type = ""
    return Item(name, Type(type), Inline("\n".join(parsed)))
示例#8
0
文件: signature.py 项目: tony/mkapi
    def set_attributes(self):
        """
        Examples:
            >>> from mkapi.core.base import Base
            >>> s = Signature(Base)
            >>> s.parameters['name'].to_tuple()
            ('name', 'str, optional', 'Name of self.')
            >>> s.attributes['html'].to_tuple()
            ('html', 'str', 'HTML output after conversion.')
        """
        items = []
        for name, (type, description) in get_attributes(self.obj).items():
            if isinstance(type, str) and type:
                type = resolve_forward_ref(self.obj, type)
            else:
                type = to_string(type, obj=self.obj) if type else ""
            if not type:
                type, description = preprocess.split_type(description)

            item = Item(name, Type(type), Inline(description))
            if is_dataclass(self.obj):
                if name in self.parameters:
                    self.parameters[name].set_description(item.description)
                if self.obj.__dataclass_fields__[name].type != InitVar:
                    items.append(item)
            else:
                items.append(item)
        self.attributes = Section("Attributes", items=items)
示例#9
0
def inherit_signature(node: Node, name: str = ""):
    """Inherits Parameters or Attributes section from signature.

    Args:
        node: Node instance.
        name: Section name: 'Parameters' or  'Attributes', or ''.
            If name is '', both sections are inherited.

    Examples:
        >>> from mkapi.core.object import get_object
        >>> base = Node(get_object('mkapi.core.base.Base'))
        >>> [item.name for item in base.docstring['Attributes'].items]
        ['html']
        >>> inherit_signature(base)
        >>> [item.name for item in base.docstring['Attributes'].items]
        ['name', 'markdown', 'html']
    """
    if not name:
        for name in ["Parameters", "Attributes"]:
            inherit_signature(node, name)
        return

    _, params = get_params(node, name)
    if not params:
        return

    node_section = node.docstring[name]
    items = []
    for item_name, type in params.items():
        if node_section is None or item_name not in node_section:
            item = Item(item_name, markdown="", type=Type(type))
        else:
            item = node_section[item_name]  # type:ignore
        items.append(item)
    node.docstring[name] = Section(name, items=items)
示例#10
0
def parse_bases(doc: Docstring, obj: Any):
    """Parses base classes to create a Base(s) line."""
    if not inspect.isclass(obj) or not hasattr(obj, "mro"):
        return
    objs = get_mro(obj)[1:]
    if not objs:
        return
    types = [get_link(obj, include_module=True) for obj in objs]
    items = [Item(type=Type(type)) for type in types if type]
    doc.set_section(Section("Bases", items=items))
示例#11
0
文件: postprocess.py 项目: RoPP/mkapi
def get_type(node: Node) -> Type:
    type = node.object.type
    if type:
        name = type.name
    else:
        for name in ["Returns", "Yields"]:
            if name in node.docstring:
                section = node.docstring[name]
                if section.type:
                    name = section.type.name
                    break
        else:
            name = ""
    return Type(name)
示例#12
0
def get_type(node: Node) -> Type:
    type = node.object.type
    if type:
        name = type.name
    else:
        for name in ["Returns", "Yields"]:
            section = node.docstring[name]
            if section and section.type:
                name = section.type.name
                break
        else:
            name = ""
    if name.startswith("("):
        name = name[1:-1]
    return Type(name)
示例#13
0
文件: signature.py 项目: tony/mkapi
    def __post_init__(self):
        if self.obj is None:
            return
        try:
            self.signature = inspect.signature(self.obj)
        except (TypeError, ValueError):
            self.set_attributes()
            return

        items = []
        for name, parameter in self.signature.parameters.items():
            if name == "self":
                continue
            elif parameter.kind is inspect.Parameter.VAR_POSITIONAL:
                name = "*" + name
            elif parameter.kind is inspect.Parameter.VAR_KEYWORD:
                name = "**" + name
            if isinstance(parameter.annotation, str):
                type = resolve_forward_ref(self.obj, parameter.annotation)
            else:
                type = to_string(parameter.annotation, obj=self.obj)
            default = parameter.default
            if default == inspect.Parameter.empty:
                self.defaults[name] = default
            else:
                self.defaults[name] = f"{default!r}"
                if not type:
                    type = "optional"
                elif not type.endswith(", optional"):
                    type += ", optional"
            items.append(Item(name, Type(type)))
        self.parameters = Section("Parameters", items=items)
        self.set_attributes()
        return_annotation = self.signature.return_annotation

        if isinstance(return_annotation, str):
            self.returns = resolve_forward_ref(self.obj, return_annotation)
        else:
            self.returns = to_string(return_annotation,
                                     "returns",
                                     obj=self.obj)
            self.yields = to_string(return_annotation, "yields", obj=self.obj)
示例#14
0
 def get_type(type: str) -> Type:
     if type.startswith("("):  # tuple
         type = type[1:-1]
     return Type(type)