Beispiel #1
0
def get_object_members(
        subject: Any,
        objpath: List[str],
        attrgetter: Callable,
        analyzer: ModuleAnalyzer = None) -> Dict[str, Attribute]:
    """Get members and attributes of target object."""
    from sphinx.ext.autodoc import INSTANCEATTR

    # the members directly defined in the class
    obj_dict = attrgetter(subject, '__dict__', {})

    members = {}  # type: Dict[str, Attribute]

    # enum members
    if isenumclass(subject):
        for name, value in subject.__members__.items():
            if name not in members:
                members[name] = Attribute(name, True, value)

        superclass = subject.__mro__[1]
        for name in obj_dict:
            if name not in superclass.__dict__:
                value = safe_getattr(subject, name)
                members[name] = Attribute(name, True, value)

    # members in __slots__
    if isclass(subject) and getattr(subject, '__slots__', None) is not None:
        from sphinx.ext.autodoc import SLOTSATTR

        for name in subject.__slots__:
            members[name] = Attribute(name, True, SLOTSATTR)

    # other members
    for name in dir(subject):
        try:
            value = attrgetter(subject, name)
            directly_defined = name in obj_dict
            name = unmangle(subject, name)
            if name and name not in members:
                members[name] = Attribute(name, directly_defined, value)
        except AttributeError:
            continue

    # annotation only member (ex. attr: int)
    if hasattr(subject, '__annotations__') and isinstance(
            subject.__annotations__, Mapping):
        for name in subject.__annotations__:
            name = unmangle(subject, name)
            if name and name not in members:
                members[name] = Attribute(name, True, INSTANCEATTR)

    if analyzer:
        # append instance attributes (cf. self.attr1) if analyzer knows
        namespace = '.'.join(objpath)
        for (ns, name) in analyzer.find_attr_docs():
            if namespace == ns and name not in members:
                members[name] = Attribute(name, True, INSTANCEATTR)

    return members
Beispiel #2
0
def mangle(subject: Any, name: str) -> str:
    """mangle the given name."""
    try:
        if isclass(subject) and name.startswith('__') and not name.endswith('__'):
            return "_%s%s" % (subject.__name__, name)
    except AttributeError:
        pass

    return name
Beispiel #3
0
def get_object_members(subject, objpath, attrgetter, analyzer=None):
    # type: (Any, List[str], Callable, Any) -> Dict[str, Attribute]  # NOQA
    """Get members and attributes of target object."""
    # the members directly defined in the class
    obj_dict = attrgetter(subject, '__dict__', {})

    members = {}  # type: Dict[str, Attribute]

    # enum members
    if isenumclass(subject):
        for name, value in subject.__members__.items():
            if name not in members:
                members[name] = Attribute(name, True, value)

        superclass = subject.__mro__[1]
        for name, value in obj_dict.items():
            if name not in superclass.__dict__:
                members[name] = Attribute(name, True, value)

    # members in __slots__
    if isclass(subject) and hasattr(subject, '__slots__'):
        from sphinx.ext.autodoc import SLOTSATTR

        for name in subject.__slots__:
            members[name] = Attribute(name, True, SLOTSATTR)

    # other members
    for name in dir(subject):
        try:
            value = attrgetter(subject, name)
            directly_defined = name in obj_dict
            if name not in members:
                members[name] = Attribute(name, directly_defined, value)
        except AttributeError:
            continue

    if analyzer:
        # append instance attributes (cf. self.attr1) if analyzer knows
        from sphinx.ext.autodoc import INSTANCEATTR

        namespace = '.'.join(objpath)
        for (ns, name) in analyzer.find_attr_docs():
            if namespace == ns and name not in members:
                members[name] = Attribute(name, True, INSTANCEATTR)

    return members
Beispiel #4
0
def unmangle(subject: Any, name: str) -> Optional[str]:
    """unmangle the given name."""
    try:
        if isclass(subject) and not name.endswith('__'):
            prefix = "_%s__" % subject.__name__
            if name.startswith(prefix):
                return name.replace(prefix, "__", 1)
            else:
                for cls in subject.__mro__:
                    prefix = "_%s__" % cls.__name__
                    if name.startswith(prefix):
                        # mangled attribute defined in parent class
                        return None
    except AttributeError:
        pass

    return name
Beispiel #5
0
def _process_docstring(app: Sphinx, what: str, name: str, obj: Any,
                       options: Any, lines: List[str]) -> None:
    """Removes already documented (by XPM) attributes from docstring

    Comes after napoleon (lesser priority) so benefit from a standardized
    output
    """
    if obj is not None and inspect.isclass(obj) and issubclass(obj, Config):
        xpminfo = getxpminfo(obj)
        names = set(xpminfo.arguments.keys())

        newlines = []
        skip = False
        for line in lines:
            if m := RE_ATTRIBUTE.match(line):
                if m.group(1) in names:
                    skip = True
            elif skip:
                if line.startswith(".."):
                    skip = False

            if not skip:
                newlines.append(line)