Пример #1
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"]
Пример #2
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)))
Пример #3
0
    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)
Пример #4
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
Пример #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 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)
Пример #7
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))
Пример #8
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))
Пример #9
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
Пример #10
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
Пример #11
0
def transform_property(node: Node, filters: List[str] = None):
    section = None
    members = []
    for member in node.members:
        object = member.object
        if "property" in object.kind:
            if section is None:
                section = node.docstring["Attributes"]
            name = object.name
            kind = object.kind
            type = object.type
            description = member.docstring.sections[0].markdown
            item = Item(name, type, Inline(description), kind=kind)
            if filters and "sourcelink" in filters:
                source_link_from_section_item(item, object)
            section.items.append(item)
        else:
            members.append(member)
    node.members = members
Пример #12
0
    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)
Пример #13
0
def test_update_item():
    a = Item("a", "int", "aaa")
    b = Item("b", "str", "bbb")
    with pytest.raises(ValueError):
        a.update(b)