示例#1
0
文件: inherit.py 项目: RoPP/mkapi
def get_section(node: Node, name: str, mode: str) -> Section:
    """Returns a tuple of (docstring section, signature section).

    Args:
        node: Node instance.
        name: Section name: `Parameters` or `Attributes`.
        mode: Mode name: `Docstring` or `Signature`.

    Examples:
        >>> node = get_node('mkapi.core.base.Type')
        >>> section = get_section(node, 'Parameters', 'Docstring')
        >>> 'name' in section
        True
        >>> section['name'].to_tuple()
        ('name', 'str, optional', '')
    """
    if mode == "Docstring":
        if name in node.docstring:
            return node.docstring[name]
        else:
            return Section(name)
    else:
        if hasattr(node.object.signature, name.lower()):
            return node.object.signature[name]
        else:
            return Section(name)
示例#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 test_docstring_copy():
    d = Docstring()
    a = Section("Parameters")
    d.set_section(a)
    assert "Parameters" in d
    assert d["Parameters"] is a
    a = Section("Arguments")
    d.set_section(a, copy=True)
    assert "Arguments" in d
    assert d["Arguments"] is not a
示例#4
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)
示例#5
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)
示例#6
0
def test_section_delete_item():
    a = Item("a", "int", "aaa")
    b = Item("b", "str", "bbb")
    c = Item("c", "float", "ccc")
    s = Section("Parameters", items=[a, b, c])
    del s["b"]
    assert "b" not in s
    with pytest.raises(KeyError):
        del s["x"]
示例#7
0
def func():
    """Internal link example.

    * [Section]() --- Imported object.
    * [](get_docstring) --- Imported object.
    * [Section.set_html]() --- Member of imported object.
    * [Section definition](Section) --- Alternative text.
    """
    return Section(), get_docstring(None)
示例#8
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))
示例#9
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 = parse_parameters(doc, style)
    elif name in ["Returns", "Yields"]:
        type, markdown = parse_returns(doc, style)
    else:
        markdown = doc
    return Section(name, markdown, items, Type(type))
示例#10
0
def get_docstring(obj: Any) -> Docstring:
    """Returns a [Docstring]() instance."""
    doc = inspect.getdoc(obj)
    if doc:
        sections = []
        for section in split_section(doc):
            sections.append(get_section(*section))
        docstring = Docstring(sections)
    elif inspect.isclass(obj) and hasattr(obj, "mro"):
        bases = obj.mro()[1:-1]
        if not bases:
            return Docstring()
        docstring = Docstring([Section()])
    else:
        return Docstring()
    postprocess(docstring, obj)
    return docstring
示例#11
0
def transform_property(node: Node):
    section = node.docstring["Attributes"]
    members = []
    for member in node.members:
        if "property" in member.object.kind:
            if section is None:
                section = Section("Attributes")
                node.docstring['Attributes'] = section
            name = member.object.name
            kind = member.object.kind
            type = member.object.type
            markdown = member.docstring.sections[0].markdown
            item = Item(name, markdown, type=type, kind=kind)
            section.items.append(item)
        else:
            members.append(member)
    node.members = members
示例#12
0
文件: postprocess.py 项目: RoPP/mkapi
def transform_members(node: Node,
                      mode: str,
                      filters: Optional[List[str]] = None):
    def is_member(kind):
        if mode in ["method", "function"]:
            return mode in kind or kind == "generator"
        else:
            return mode in kind and "method" not in kind

    members = [
        member for member in node.members if is_member(member.object.kind)
    ]
    if not members:
        return

    name = mode[0].upper() + mode[1:] + ("es" if mode == "class" else "s")
    section = Section(name)
    for member in members:
        object = member.object
        kind = object.kind
        type = get_type(member)
        if member.docstring and "" in member.docstring:
            description = member.docstring[""].markdown
            if "\n\n" in description:
                description = description.split("\n\n")[0]
        else:
            description = ""
        item = Item(object.name, type, Inline(description), kind)
        item.markdown, url = "", ""
        if filters and ("link" in filters or "all" in filters):
            url = "#" + object.id
        elif filters and "apilink" in filters:
            url = "../" + node.object.id + "#" + object.id
        signature: Dict[str, Any] = {}
        if object.kind not in ["class", "dataclass"]:
            args = [item.name for item in object.signature.parameters.items]
            signature["arguments"] = args
        else:
            signature["arguments"] = None
        item.html = renderer.render_object_member(object.name, url, signature)
        if filters and "sourcelink" in filters:
            source_link_from_section_item(item, object)
        section.items.append(item)
    node.docstring.set_section(section)
示例#13
0
def inherit_base(node: Node, base: Node, name: str = ""):
    """Inherits Parameters or Attributes section from base class.

    Args:
        node: Node instance.
        base: Node instance of a super class.
        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'))
        >>> node = Node(get_object('mkapi.core.base.Type'))
        >>> [item.name for item in base.docstring['Parameters'].items]
        ['name', 'markdown']
        >>> node.docstring['Parameters'] is None
        True
        >>> inherit_base(node, base)
        >>> [item.name for item in node.docstring['Parameters'].items]
        ['name', 'markdown']
    """
    if not name:
        for name in ["Parameters", "Attributes"]:
            inherit_base(node, base, name)
        return

    base_section = base.docstring[name]
    if base_section is None:
        return
    _, node_params = get_params(node, name)
    _, base_params = get_params(base, name)
    node_section = node.docstring[name]
    items = []
    for item in base_section.items:
        if node_section is None or item.name not in node_section:
            if (item.name in node_params
                    and node_params[item.name] == base_params[item.name]):
                items.append(item)
    if node_section is not None:
        for item in node_section.items:
            if item not in items:
                items.append(item)
    node.docstring[name] = Section(name, items=items)  # type:ignore
示例#14
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)
示例#15
0
def transform_members(node: Node,
                      mode: str,
                      filters: Optional[List[str]] = None):
    def is_member(kind):
        if mode in ["method", "function"]:
            return mode in kind or kind == "generator"
        else:
            return mode in kind and 'method' not in kind

    members = [
        member for member in node.members if is_member(member.object.kind)
    ]
    if not members:
        return

    name = mode[0].upper() + mode[1:] + ("es" if mode == "class" else "s")
    section = Section(name)
    for member in members:
        object = member.object
        kind = object.kind
        type = get_type(member)
        section_ = member.docstring[""]
        if section_:
            markdown = section_.markdown
            if "\n\n" in markdown:
                markdown = markdown.split("\n\n")[0]
        item = Item(name, markdown, type=type, kind=kind)
        item.markdown, url, signature = "", "", ""
        if filters and "link" in filters:
            url = "#" + object.id
        if object.kind not in ["class", "dataclass"]:
            signature = "(" + ",".join(
                object.signature.parameters.keys()) + ")"
        item.html = renderer.render_object_member(object.name, url, signature)
        section.items.append(item)
    node.docstring[name] = section
示例#16
0
def test_section_merge():
    a = Section("a")
    b = Section("b")
    with pytest.raises(ValueError):
        a.merge(b)