Ejemplo n.º 1
0
    def get_members(clazz, obj, typ):
        names = set()
        items = []

        # the default dir
        for name in dir(obj):
            try:
                documenter = get_documenter(safe_getattr(obj, name), obj)
            except AttributeError:
                continue
            if documenter.objtype == typ and not name.startswith('_'):
                if name not in AutoCosmoSummary.exclude:
                    items.append((clazz,name))
                    names.add(name) # keep track of method/attribute conflicts

        # the delegate dro
        for n in obj.dro:
            for name in dir(n):
                try:
                    documenter = get_documenter(safe_getattr(n, name), n)
                except AttributeError:
                    continue

                # dont do conflicts
                if name not in names:
                    if documenter.objtype == typ and not name.startswith('_'):
                        if name not in AutoCosmoSummary.exclude:
                            x = "%s.%s" %(n.__module__, n.__name__)
                            items.append((x,name))
                            names.add(name)

        return ['~%s.%s' %item for item in sorted(items, key=lambda x: x[1])]
Ejemplo n.º 2
0
            def get_members (obj, typ):
                items = [
                    (name, get_methods_etc(getattr(obj, name))) for name in dir(obj)
                    if get_documenter(getattr(obj, name), obj).objtype == typ
                ]

                return items
Ejemplo n.º 3
0
            def get_members_class(obj, typ, include_public=[],
                                  include_base=False):
                """
                typ = None -> all
                include_base -> include attrs that are from a base class
                """
                items = []

                # using dir gets all of the attributes, including the elements
                # from the base class, otherwise use __slots__ or __dict__
                if include_base:
                    names = dir(obj)
                else:
                    if hasattr(obj, '__slots__'):
                        names = tuple(getattr(obj, '__slots__'))
                    else:
                        names = getattr(obj, '__dict__').keys()

                for name in names:
                    try:
                        documenter = get_documenter(safe_getattr(obj, name),
                                                    obj)
                    except AttributeError:
                        continue
                    if typ is None or documenter.objtype == typ:
                        items.append(name)
                public = [x for x in items
                          if x in include_public or not x.startswith('_')]
                return public, items
Ejemplo n.º 4
0
 def get_members(obj, typ, include_public=[]):
     items = [
         name for name in dir(obj)
         if get_documenter(getattr(obj, name), obj).objtype == typ
     ]
     public = [x for x in items
               if x in include_public or not x.startswith('_')]
     return public, items
Ejemplo n.º 5
0
 def get_members(obj, typ, include_public=[]):
     items = []
     for name in dir(obj):
         try:
             if get_documenter(getattr(obj, name)).objtype == typ:
                 items.append(name)
         except AttributeError:
             warn("[autosummary] problem accessing attribute " "'%s' in '%s'." % (name, obj))
     public = [x for x in items if x in include_public or not x.startswith("_")]
     return public, items
Ejemplo n.º 6
0
 def get_members(obj, typ, include_public=[]):
     items = []
     for name in dir(obj):
         try:
             documenter = get_documenter(safe_getattr(obj, name), obj)
         except AttributeError:
             continue
         if documenter.objtype == typ:
             items.append(name)
     public = [x for x in items if x in include_public or not x.startswith("_")]
     return public, items
Ejemplo n.º 7
0
 def get_members(obj, typ, include_public=None):
     if not include_public:
         include_public = []
     items = []
     for name in sorted(obj.__dict__.keys()):#dir(obj):
         try:
             documenter = get_documenter(AutoAutoSummary.app, safe_getattr(obj, name), obj)
         except AttributeError:
             continue
         if documenter.objtype in typ:
             items.append(name)
     public = [x for x in items if x in include_public or not x.startswith('_')]
     return public, items
Ejemplo n.º 8
0
 def get_members(obj, typ, include_public=None):
     if not include_public:
         include_public = []
     items = []
     for name in dir(obj):
         try:
             documenter = get_documenter(app, safe_getattr(obj, name), obj)
         except AttributeError:
             continue
         if documenter.objtype == typ:
             items.append(name)
     public = [x for x in items if x in include_public or not x.startswith('_')]
     return public, items
Ejemplo n.º 9
0
def get_members(app, obj, typ, include_public=(), imported=False):
    items = []
    for name in dir(obj):
        try:
            obj_name = safe_getattr(obj, name)
            try:
                documenter = get_documenter(app, obj_name, obj)
            except TypeError:
                documenter = get_documenter(obj_name, obj)

        except AttributeError:
            continue
        if documenter.objtype == typ:
            try:
                cond = imported or (obj_name.__module__ == obj.__name__)
            except AttributeError:
                cond = True

            if cond:
                items.append(name)
    public = [x for x in items if x in include_public or not x.startswith('_')]
    return public, items
Ejemplo n.º 10
0
 def get_members_mod(obj, typ, include_public=[]):
     """
     typ = None -> all
     """
     items = []
     for name in dir(obj):
         try:
             if SPHINX_LT_17:
                 documenter = get_documenter(
                     safe_getattr(obj, name), obj)
             else:
                 documenter = get_documenter(
                     app, safe_getattr(obj, name), obj)
         except AttributeError:
             continue
         if typ is None or documenter.objtype == typ:
             items.append(name)
     public = [
         x for x in items
         if x in include_public or not x.startswith('_')
     ]
     return public, items
Ejemplo n.º 11
0
    def get_members(doc,
                    obj,
                    typ,
                    include_public=None,
                    signal=False,
                    enum=False):
        try:
            if not include_public:
                include_public = []
            items = []

            for name in dir(obj):
                if name not in obj.__dict__.keys():
                    continue
                try:
                    chobj = safe_getattr(obj, name)
                    documenter = get_documenter(doc.settings.env.app, chobj,
                                                obj)
                    #cl = get_class_that_defined_method(chobj)
                    #print(name, chobj.__qualname__, type(chobj), issubclass(chobj, Enum), documenter.objtype)
                    if documenter.objtype == typ:
                        if typ == 'attribute':
                            if signal and type(
                                    chobj) != PyQt5.QtCore.pyqtSignal:
                                continue
                            if not signal and type(
                                    chobj) == PyQt5.QtCore.pyqtSignal:
                                continue
                            # skip monkey patched enums
                            # the monkeypatched enums coming out of scoped enum inherit Enum
                            # while the standard/old ones do not
                            if hasattr(chobj, '__objclass__') and issubclass(
                                    chobj.__objclass__, Enum):
                                continue
                        elif typ == 'class':
                            if enum:
                                if not issubclass(chobj, Enum):
                                    continue
                            if not enum and issubclass(chobj, Enum):
                                continue
                        items.append(name)
                except AttributeError:
                    continue
            public = [
                x for x in items
                if x in include_public or not x.startswith('_')
            ]
            return public, items
        except BaseException as e:
            print(str(e))
            raise e
Ejemplo n.º 12
0
    def run(self):
        module_name = str(self.arguments[0])
        module = importlib.import_module(module_name)

        analyzer = ModuleAnalyzer.for_module(module_name)
        attr_docs = analyzer.find_attr_docs()

        with open(module.__file__) as module_file:
            symbols = symtable.symtable(module_file.read(), module.__file__, "exec")

        members = []

        for name in dir(module):
            member = getattr(module, name)

            # Ignore private members
            if name.startswith("_"):
                continue

            # Ignore imported modules
            if isinstance(member, types.ModuleType):
                continue

            # Ignore members imported from other modules
            member_module_name = getattr(member, "__module__", None)
            if member_module_name is None:
                try:
                    if symbols.lookup(name).is_imported():
                        continue
                except KeyError:
                    continue
            else:
                if member_module_name != module_name:
                    continue

            documenter = get_documenter(self.env.app, member, module)

            # Ignore data items that do not have docstrings
            if documenter.objtype == "data" and ("", name) not in attr_docs:
                continue

            members.append(name)

        # Sort members in the order they appear in source code
        tagorder = analyzer.tagorder
        members.sort(key=lambda name: tagorder.get(name, len(tagorder)))

        self.content = [f"{module_name}.{member}" for member in members]

        return super().run()
Ejemplo n.º 13
0
 def get_members(app, obj, typ, include_public=None):
     if not include_public:
         include_public = []
     items = []
     for name in vars(obj):
         try:
             documenter = get_documenter(app, safe_getattr(obj, name), obj)
         except AttributeError:
             continue
         if documenter.objtype == typ:
             items.append(name)
     items.sort()
     public = [x for x in items if x in include_public or not x.startswith('_')]
     return public, items
Ejemplo n.º 14
0
 def get_members(obj, typ, include_public=[]):
     # type: (Any, unicode, List[unicode]) -> Tuple[List[unicode], List[unicode]]
     items = []  # type: List[unicode]
     for name in dir(obj):
         try:
             documenter = get_documenter(safe_getattr(obj, name),
                                         obj)
         except AttributeError:
             continue
         if documenter.objtype == typ:
             items.append(name)
     public = [x for x in items
               if x in include_public or not x.startswith('_')]
     return public, items
Ejemplo n.º 15
0
 def get_members(obj, typ, include_public=[]):
     items = []
     for name in dir(obj):
         try:
             if get_documenter(getattr(obj, name)).objtype == typ:
                 items.append(name)
         except AttributeError:
             warn("[autosummary] problem accessing attribute "
                  "'%s' in '%s'." % (name, obj))
     public = [
         x for x in items
         if x in include_public or not x.startswith('_')
     ]
     return public, items
Ejemplo n.º 16
0
def get_members(app, obj, typ, include_public=(), imported=False):
    items = []
    for name in dir(obj):
        try:
            obj_name = safe_getattr(obj, name)
            try:
                documenter = get_documenter(app, obj_name, obj)
            except TypeError:
                documenter = get_documenter(obj_name, obj)

        except AttributeError:
            continue
        if documenter.objtype == typ:
            try:
                cond = imported or (obj_name.__module__ == obj.__name__)
            except AttributeError:
                cond = True

            if cond:
                items.append(name)
    public = [x for x in items
              if x in include_public or not x.startswith('_')]
    return public, items
Ejemplo n.º 17
0
            def get_members_class(obj,
                                  typ,
                                  include_public=[],
                                  include_base=False):
                """
                typ = None -> all
                include_base -> include attrs that are from a base class
                """
                items = []

                # using dir gets all of the attributes, including the elements
                # from the base class, otherwise use __slots__ or __dict__
                if include_base:
                    names = dir(obj)
                else:
                    if hasattr(obj, '__slots__'):
                        names = tuple(getattr(obj, '__slots__'))
                    else:
                        names = getattr(obj, '__dict__').keys()

                for name in names:
                    try:
                        if SPHINX_LT_17:
                            documenter = get_documenter(
                                safe_getattr(obj, name), obj)
                        else:
                            documenter = get_documenter(
                                app, safe_getattr(obj, name), obj)
                    except AttributeError:
                        continue
                    if typ is None or documenter.objtype == typ:
                        items.append(name)
                public = [
                    x for x in items
                    if x in include_public or not x.startswith('_')
                ]
                return public, items
Ejemplo n.º 18
0
 def get_members(obj, typ, include_public=[], imported=False):
     # type: (Any, unicode, List[unicode], bool) -> Tuple[List[unicode], List[unicode]]  # NOQA
     items = []  # type: List[unicode]
     for name in dir(obj):
         try:
             value = safe_getattr(obj, name)
         except AttributeError:
             continue
         documenter = get_documenter(value, obj)
         if documenter.objtype == typ:
             if imported or getattr(value, '__module__', None) == obj.__name__:
                 items.append(name)
     public = [x for x in items
               if x in include_public or not x.startswith('_')]
     return public, items
def get_public_members(obj, typ, include_public=[]):
    items = []
    for name in dir(obj):
        attr = None
        try:
            attr = safe_getattr(obj, name)
            documenter = get_documenter(attr, obj)
        except AttributeError:
            continue

        attr_file = get_file(attr)
        if ((documenter.objtype == typ)
                and ((attr_file == get_file(obj)) or (attr_file is None))
                and ((name in include_public) or not name.startswith('_'))):
            items.append(name)
    return items
Ejemplo n.º 20
0
 def get_members(obj: Any, types: Set[str], include_public: List[str] = [],
                 imported: bool = True) -> Tuple[List[str], List[str]]:
     items = []  # type: List[str]
     for name in dir(obj):
         try:
             value = safe_getattr(obj, name)
         except AttributeError:
             continue
         documenter = get_documenter(app, value, obj)
         if documenter.objtype in types:
             if imported or getattr(value, '__module__', None) == obj.__name__:
                 # skip imported members if expected
                 items.append(name)
     public = [x for x in items
               if x in include_public or not x.startswith('_')]
     return public, items
Ejemplo n.º 21
0
 def get_members(obj, typ, include_public=[]):
     # type: (Any, unicode, List[unicode]) -> Tuple[List[unicode], List[unicode]]
     items = []  # type: List[unicode]
     for name in dir(obj):
         try:
             documenter = get_documenter(safe_getattr(obj, name),
                                         obj)
         except AttributeError:
             continue
         if documenter.objtype == typ:
             items.append(name)
     public = [
         x for x in items
         if x in include_public or not x.startswith('_')
     ]
     return public, items
Ejemplo n.º 22
0
 def get_members_mod(obj, typ, include_public=[]):
     """
     typ = None -> all
     """
     items = []
     for name in dir(obj):
         try:
             documenter = get_documenter(safe_getattr(obj, name),
                                         obj)
         except AttributeError:
             continue
         if typ is None or documenter.objtype == typ:
             items.append(name)
     public = [x for x in items
               if x in include_public or not x.startswith('_')]
     return public, items
Ejemplo n.º 23
0
 def get_members(obj, typ, include_public=[], imported=True):
     # type: (Any, unicode, List[unicode], bool) -> Tuple[List[unicode], List[unicode]]  # NOQA
     items = []  # type: List[unicode]
     for name in dir(obj):
         try:
             value = safe_getattr(obj, name)
         except AttributeError:
             continue
         documenter = get_documenter(app, value, obj)
         if documenter.objtype == typ:
             if imported or getattr(value, '__module__', None) == obj.__name__:
                 # skip imported members if expected
                 items.append(name)
     public = [x for x in items
               if x in include_public or not x.startswith('_')]
     return public, items
Ejemplo n.º 24
0
            def get_members_class(obj,
                                  typ,
                                  include_public=[],
                                  include_base=False):
                """
                typ = None -> all
                include_base -> include attrs that are from a base class
                """
                items = []

                # using dir gets all of the attributes, including the elements
                # from the base class, otherwise use __slots__ or __dict__
                if include_base:
                    names = dir(obj)
                else:
                    # Classes deriving from an ABC using the `abc` module will
                    # have an empty `__slots__` attribute in Python 3, unless
                    # other slots were declared along the inheritance chain. If
                    # the ABC-derived class has empty slots, we'll use the
                    # class `__dict__` instead.
                    declares_slots = (hasattr(obj, '__slots__')
                                      and not (type(obj) is abc.ABCMeta
                                               and len(obj.__slots__) == 0))

                    if declares_slots:
                        names = tuple(getattr(obj, '__slots__'))
                    else:
                        names = getattr(obj, '__dict__').keys()

                for name in names:
                    try:
                        documenter = get_documenter(app,
                                                    safe_getattr(obj,
                                                                 name), obj)
                    except AttributeError:
                        continue
                    if typ is None or documenter.objtype == typ:
                        items.append(name)
                    elif typ == 'attribute' and documenter.objtype == 'property':
                        # In Sphinx 2.0 and above, properties have a separate
                        # objtype, but we treat them the same here.
                        items.append(name)
                public = [
                    x for x in items
                    if x in include_public or not x.startswith('_')
                ]
                return public, items
Ejemplo n.º 25
0
 def get_members(self, obj, typ, include_public=None):
     if not include_public:
         include_public = []
     items = []
     for name in obj.__dict__.keys():
         try:
             documenter = get_documenter(obj=safe_getattr(obj, name),
                                         parent=obj,
                                         app=self.env.app)
         except AttributeError:
             continue
         if documenter.objtype == typ:
             items.append(name)
     public = [
         x for x in items if x in include_public or not x.startswith('_')
     ]
     return public, items
Ejemplo n.º 26
0
Archivo: conf.py Proyecto: b-sea/sprout
    def get_members(obj, typ, include_public=None):
        if not include_public:
            include_public = []
        items = []

        members = dir(obj)
        members.sort(key=AutoAutoSummary._customSort)
        for name in members:
            try:
                documenter = get_documenter(safe_getattr(obj, name), obj)
            except AttributeError:
                continue
            if documenter.objtype == typ:
                items.append(name)
        public = [
            x for x in items if x in include_public or not x.startswith('_')
        ]
        return public, items
Ejemplo n.º 27
0
def get_members(obj, typ, include_public=()):
    __all__ = getattr(obj, '__all__', [])
    skip_all = not __all__
    __all__ += include_public

    items = []
    for name in dir(obj):
        try:
            documenter = get_documenter(safe_getattr(obj, name), obj)
        except AttributeError:
            continue
        if documenter.objtype == typ:
            items.append(name)

    public = [x for x in items if x in __all__ or skip_all and not x.startswith('_')]
    # only members with docstrings are considered public
    public = [x for x in public if safe_getattr(obj, x).__doc__]
    return public, items
Ejemplo n.º 28
0
            def get_members(obj, typ, include_public=[]):
                items = []
                for name in dir(obj):
                    try:
                        documenter = get_documenter(
                            app, safe_getattr(obj, name), obj)
                    except AttributeError:
                        continue
                    if documenter.objtype == typ:
                        items.append(name)

                if hasattr(obj, "__all__"):
                    public = [x for x in items
                              if x in obj.__all__]
                else:
                    public = [x for x in items
                              if x in include_public or not x.startswith('_')]

                return public, items
Ejemplo n.º 29
0
 def get_members(obj, typ, include_public=[]):
     items = []
     want_all = self.options.inherited_members or \
                self.options.members is ALL
     members = zip(*self.get_object_members(want_all)[1])[0]
     if self.options.exclude_members:
         members = [m for m in members if
                    m not in self.options.exclude_members]
     for name in members:
         try:
             documenter = get_documenter(safe_getattr(obj, name),
                                         obj)
         except AttributeError:
             continue
         if documenter.objtype == typ:
             items.append(name)
     public = [x for x in items
               if x in include_public or not x.startswith('_')]
     return public, items
Ejemplo n.º 30
0
 def get_members(obj, typ, include_public=[]):
     items = []
     want_all = (self.options.inherited_members or
                 self.options.members is ALL)
     members = zip(*self.get_object_members(want_all)[1])[0]
     if self.options.exclude_members:
         members = [m for m in members if
                    m not in self.options.exclude_members]
     for name in members:
         try:
             documenter = get_documenter(
                 safe_getattr(obj, name), obj)
         except AttributeError:
             continue
         if documenter.objtype == typ:
             items.append(name)
     public = [x for x in items
               if x in include_public or not x.startswith('_')]
     return public, items
Ejemplo n.º 31
0
    def get_members(obj: Any, types: Set[str], include_public: List[str] = [],
                    imported: bool = True) -> Tuple[List[str], List[str]]:
        items: List[str] = []
        public: List[str] = []

        all_members = get_all_members(obj)
        for name, value in all_members.items():
            documenter = get_documenter(app, value, obj)
            if documenter.objtype in types:
                # skip imported members if expected
                if imported or getattr(value, '__module__', None) == obj.__name__:
                    skipped = skip_member(value, name, documenter.objtype)
                    if skipped is True:
                        pass
                    elif skipped is False:
                        # show the member forcedly
                        items.append(name)
                        public.append(name)
                    else:
                        items.append(name)
                        if name in include_public or not name.startswith('_'):
                            # considers member as public
                            public.append(name)
        return public, items
Ejemplo n.º 32
0
    def _get_members(self, class_obj, member_type, include_in_public=None):
        """
        Return class members of the specified type.

        class_obj: Class object.

        member_type: Member type ('method' or 'attribute').

        include_in_public: set/list/tuple with member names that should be
          included in public members in addition to the public names (those
          starting without underscore).

        Returns:
          tuple(public_members, all_members): Names of the class members of
            the specified member type (public / all).
        """
        try:
            app = self.state.document.settings.env.app
        except AttributeError:
            app = None
        if not include_in_public:
            include_in_public = []
        all_members = []
        for member_name in dir(class_obj):
            try:
                documenter = get_documenter(
                    app, safe_getattr(class_obj, member_name), class_obj)
            except AttributeError:
                continue
            if documenter.objtype == member_type:
                all_members.append(member_name)
        public_members = [
            x for x in all_members
            if x in include_in_public or not x.startswith('_')
        ]
        return public_members, all_members
Ejemplo n.º 33
0
def generate_autosummary_content(name: str, obj: Any, parent: Any,
                                 template: AutosummaryRenderer, template_name: str,
                                 imported_members: bool, app: Any,
                                 recursive: bool, context: Dict) -> str:
    doc = get_documenter(app, obj, parent)

    def skip_member(obj: Any, name: str, objtype: str) -> bool:
        try:
            return app.emit_firstresult('autodoc-skip-member', objtype, name,
                                        obj, False, {})
        except Exception as exc:
            logger.warning(__('autosummary: failed to determine %r to be documented, '
                              'the following exception was raised:\n%s'),
                           name, exc, type='autosummary')
            return False

    def get_members(obj: Any, types: Set[str], include_public: List[str] = [],
                    imported: bool = True) -> Tuple[List[str], List[str]]:
        items = []  # type: List[str]
        public = []  # type: List[str]
        for name in dir(obj):
            try:
                value = safe_getattr(obj, name)
            except AttributeError:
                continue
            documenter = get_documenter(app, value, obj)
            if documenter.objtype in types:
                # skip imported members if expected
                if imported or getattr(value, '__module__', None) == obj.__name__:
                    skipped = skip_member(value, name, documenter.objtype)
                    if skipped is True:
                        pass
                    elif skipped is False:
                        # show the member forcedly
                        items.append(name)
                        public.append(name)
                    else:
                        items.append(name)
                        if name in include_public or not name.startswith('_'):
                            # considers member as public
                            public.append(name)
        return public, items

    def get_modules(obj: Any) -> Tuple[List[str], List[str]]:
        items = []  # type: List[str]
        for _, modname, ispkg in pkgutil.iter_modules(obj.__path__):
            fullname = name + '.' + modname
            items.append(fullname)
        public = [x for x in items if not x.split('.')[-1].startswith('_')]
        return public, items

    ns = {}  # type: Dict[str, Any]
    ns.update(context)

    if doc.objtype == 'module':
        ns['members'] = dir(obj)
        ns['functions'], ns['all_functions'] = \
            get_members(obj, {'function'}, imported=imported_members)
        ns['classes'], ns['all_classes'] = \
            get_members(obj, {'class'}, imported=imported_members)
        ns['exceptions'], ns['all_exceptions'] = \
            get_members(obj, {'exception'}, imported=imported_members)
        ispackage = hasattr(obj, '__path__')
        if ispackage and recursive:
            ns['modules'], ns['all_modules'] = get_modules(obj)
    elif doc.objtype == 'class':
        ns['members'] = dir(obj)
        ns['inherited_members'] = \
            set(dir(obj)) - set(obj.__dict__.keys())
        ns['methods'], ns['all_methods'] = \
            get_members(obj, {'method'}, ['__init__'])
        ns['attributes'], ns['all_attributes'] = \
            get_members(obj, {'attribute', 'property'})

    modname, qualname = split_full_qualified_name(name)
    if doc.objtype in ('method', 'attribute', 'property'):
        ns['class'] = qualname.rsplit(".", 1)[0]

    if doc.objtype in ('class',):
        shortname = qualname
    else:
        shortname = qualname.rsplit(".", 1)[-1]

    ns['fullname'] = name
    ns['module'] = modname
    ns['objname'] = qualname
    ns['name'] = shortname

    ns['objtype'] = doc.objtype
    ns['underline'] = len(name) * '='

    if template_name:
        return template.render(template_name, ns)
    else:
        return template.render(doc.objtype, ns)
Ejemplo n.º 34
0
def _get_members(mod,
                 typ=None,
                 include_imported=False,
                 as_refs=False,
                 in__all__=False):
    """Get (filtered) public/total members of the module or package `mod`.

    Args:
        mod: object resulting from importing a module or package
        typ: filter on members. If None, include all members. If one of
            'function', 'class', 'exception', 'data', only include members of
            the matching type
        include_imported: If True, also include members that are imports
        as_refs: If True, return ReST-formatted reference strings for all
            members, instead of just their names. In combinations with
            `include_imported` or `in__all__`, these link to the original
            location where the member is defined
        in__all__: If True, return only members that are in ``mod.__all__``

    Returns:
        lists `public` and `items`. The lists contains the public and private +
        public  members, as strings.

    Note:
        For data members, there is no way to tell whether they were imported or
        defined locally (without parsing the source code). A module may define
        one or both attributes

        __local_data__: list of names of data objects defined locally
        __imported_data__: dict of names to ReST-formatted references of where
            a data object originates

        If either one of these attributes is present, the member will be
        classified accordingly. Otherwise, it will be classified as local if it
        appeard in the __all__ list, or as imported otherwise

    """
    roles = {
        'function': 'func',
        'module': 'mod',
        'class': 'class',
        'exception': 'exc',
        'data': 'data'
    }

    # not included, because they cannot occur at modul level:
    #   'method': 'meth', 'attribute': 'attr', 'instanceattribute': 'attr'

    def check_typ(typ, mod, member):
        """Check if mod.member is of the desired typ"""
        documenter = get_documenter(member, mod)
        if typ is None:
            return True
        if typ == getattr(documenter, 'objtype', None):
            return True
        if hasattr(documenter, 'directivetype'):
            return roles[typ] == getattr(documenter, 'directivetype')

    def is_local(mod, member, name):
        """Check whether mod.member is defined locally in module mod"""
        if hasattr(member, '__module__'):
            return getattr(member, '__module__') == mod.__name__
        else:
            # we take missing __module__ to mean the member is a data object
            if hasattr(mod, '__local_data__'):
                return name in getattr(mod, '__local_data__')
            if hasattr(mod, '__imported_data__'):
                return name not in getattr(mod, '__imported_data__')
            else:
                return name in getattr(mod, '__all__', [])

    if typ is not None and typ not in roles:
        raise ValueError("typ must be None or one of %s" %
                         str(list(roles.keys())))
    items = []
    public = []
    all_list = getattr(mod, '__all__', [])
    for name in dir(mod):
        try:
            member = safe_getattr(mod, name)
        except AttributeError:
            continue
        if check_typ(typ, mod, member):
            if in__all__ and name not in all_list:
                continue
            if include_imported or is_local(mod, member, name):
                if as_refs:
                    documenter = get_documenter(member, mod)
                    role = roles.get(documenter.objtype, 'obj')
                    ref = _get_member_ref_str(name,
                                              obj=member,
                                              role=role,
                                              known_refs=getattr(
                                                  mod, '__imported_data__',
                                                  None))
                    items.append(ref)
                    if not name.startswith('_'):
                        public.append(ref)
                else:
                    items.append(name)
                    if not name.startswith('_'):
                        public.append(name)
    return public, items
Ejemplo n.º 35
0
def generate_autosummary_content(name: str, obj: Any, parent: Any,
                                 template: AutosummaryRenderer, template_name: str,
                                 imported_members: bool, app: Any) -> str:
    doc = get_documenter(app, obj, parent)

    if template_name is None:
        template_name = 'autosummary/%s.rst' % doc.objtype
        if not template.exists(template_name):
            template_name = 'autosummary/base.rst'

    def skip_member(obj: Any, name: str, objtype: str) -> bool:
        try:
            return app.emit_firstresult('autodoc-skip-member', objtype, name,
                                        obj, False, {})
        except Exception as exc:
            logger.warning(__('autosummary: failed to determine %r to be documented.'
                              'the following exception was raised:\n%s'),
                           name, exc, type='autosummary')
            return False

    def get_members(obj: Any, types: Set[str], include_public: List[str] = [],
                    imported: bool = True) -> Tuple[List[str], List[str]]:
        items = []  # type: List[str]
        public = []  # type: List[str]
        for name in dir(obj):
            try:
                value = safe_getattr(obj, name)
            except AttributeError:
                continue
            documenter = get_documenter(app, value, obj)
            if documenter.objtype in types:
                # skip imported members if expected
                if imported or getattr(value, '__module__', None) == obj.__name__:
                    skipped = skip_member(value, name, documenter.objtype)
                    if skipped is True:
                        pass
                    elif skipped is False:
                        # show the member forcedly
                        items.append(name)
                        public.append(name)
                    else:
                        items.append(name)
                        if name in include_public or not name.startswith('_'):
                            # considers member as public
                            public.append(name)
        return public, items

    ns = {}  # type: Dict[str, Any]

    if doc.objtype == 'module':
        ns['members'] = dir(obj)
        ns['functions'], ns['all_functions'] = \
            get_members(obj, {'function'}, imported=imported_members)
        ns['classes'], ns['all_classes'] = \
            get_members(obj, {'class'}, imported=imported_members)
        ns['exceptions'], ns['all_exceptions'] = \
            get_members(obj, {'exception'}, imported=imported_members)
    elif doc.objtype == 'class':
        ns['members'] = dir(obj)
        ns['inherited_members'] = \
            set(dir(obj)) - set(obj.__dict__.keys())
        ns['methods'], ns['all_methods'] = \
            get_members(obj, {'method'}, ['__init__'])
        ns['attributes'], ns['all_attributes'] = \
            get_members(obj, {'attribute', 'property'})

    parts = name.split('.')
    if doc.objtype in ('method', 'attribute', 'property'):
        mod_name = '.'.join(parts[:-2])
        cls_name = parts[-2]
        obj_name = '.'.join(parts[-2:])
        ns['class'] = cls_name
    else:
        mod_name, obj_name = '.'.join(parts[:-1]), parts[-1]

    ns['fullname'] = name
    ns['module'] = mod_name
    ns['objname'] = obj_name
    ns['name'] = parts[-1]

    ns['objtype'] = doc.objtype
    ns['underline'] = len(name) * '='

    return template.render(template_name, ns)
Ejemplo n.º 36
0
def generate_automodsumm_docs(lines, srcfn, suffix='.rst', warn=None,
                              info=None, base_path=None, builder=None,
                              template_dir=None):
    """
    This function is adapted from
    `sphinx.ext.autosummary.generate.generate_autosummmary_docs` to
    generate source for the automodsumm directives that should be
    autosummarized. Unlike generate_autosummary_docs, this function is
    called one file at a time.
    """
    import os

    from sphinx import package_dir
    from sphinx.jinja2glue import BuiltinTemplateLoader
    from sphinx.ext.autosummary import import_by_name, get_documenter
    from sphinx.ext.autosummary.generate import (find_autosummary_in_lines,
                                                 _simple_info, _simple_warn)
    from sphinx.util.osutil import ensuredir
    from sphinx.util.inspect import safe_getattr
    from jinja2 import FileSystemLoader, TemplateNotFound
    from jinja2.sandbox import SandboxedEnvironment

    if info is None:
        info = _simple_info
    if warn is None:
        warn = _simple_warn

    #info('[automodsumm] generating automodsumm for: ' + srcfn)

    # create our own templating environment
    template_dirs = [os.path.join(package_dir, 'ext',
                                  'autosummary', 'templates')]
    if builder is not None:
        # allow the user to override the templates
        template_loader = BuiltinTemplateLoader()
        template_loader.init(builder, dirs=template_dirs)
    else:
        if template_dir:
            template_dirs.insert(0, template_dir)
        template_loader = FileSystemLoader(template_dirs)
    template_env = SandboxedEnvironment(loader=template_loader)

    # read
    #items = find_autosummary_in_files(sources)
    items = find_autosummary_in_lines(lines, filename=srcfn)
    if len(items) > 0:
        msg = '[automodsumm] {1}: found {0} automodsumm entries to generate'
        info(msg.format(len(items), srcfn))

#    gennms = [item[0] for item in items]
#    if len(gennms) > 20:
#        gennms = gennms[:10] + ['...'] + gennms[-10:]
#    info('[automodsumm] generating autosummary for: ' + ', '.join(gennms))

    # remove possible duplicates
    items = dict([(item, True) for item in items]).keys()

    # keep track of new files
    new_files = []

    # write
    for name, path, template_name in sorted(items):
        if path is None:
            # The corresponding autosummary:: directive did not have
            # a :toctree: option
            continue

        path = os.path.abspath(path)
        ensuredir(path)

        try:
            name, obj, parent = import_by_name(name)
        except ImportError, e:
            warn('[automodapi] failed to import %r: %s' % (name, e))
            continue

        fn = os.path.join(path, name + suffix)

        # skip it if it exists
        if os.path.isfile(fn):
            continue

        new_files.append(fn)

        f = open(fn, 'w')

        try:
            doc = get_documenter(obj, parent)

            if template_name is not None:
                template = template_env.get_template(template_name)
            else:
                tmplstr = 'autosummary/%s.rst'
                try:
                    template = template_env.get_template(tmplstr % doc.objtype)
                except TemplateNotFound:
                    template = template_env.get_template(tmplstr % 'base')

            def get_members(obj, typ, include_public=[]):
                items = []
                for name in dir(obj):
                    try:
                        documenter = get_documenter(safe_getattr(obj, name),
                                                    obj)
                    except AttributeError:
                        continue
                    if documenter.objtype == typ:
                        items.append(name)
                public = [x for x in items
                          if x in include_public or not x.startswith('_')]
                return public, items

            ns = {}

            if doc.objtype == 'module':
                ns['members'] = dir(obj)
                ns['functions'], ns['all_functions'] = \
                                   get_members(obj, 'function')
                ns['classes'], ns['all_classes'] = \
                                 get_members(obj, 'class')
                ns['exceptions'], ns['all_exceptions'] = \
                                   get_members(obj, 'exception')
            elif doc.objtype == 'class':
                ns['members'] = dir(obj)
                ns['methods'], ns['all_methods'] = \
                                 get_members(obj, 'method', ['__init__'])
                ns['attributes'], ns['all_attributes'] = \
                                 get_members(obj, 'attribute')

            parts = name.split('.')
            if doc.objtype in ('method', 'attribute'):
                mod_name = '.'.join(parts[:-2])
                cls_name = parts[-2]
                obj_name = '.'.join(parts[-2:])
                ns['class'] = cls_name
            else:
                mod_name, obj_name = '.'.join(parts[:-1]), parts[-1]

            ns['fullname'] = name
            ns['module'] = mod_name
            ns['objname'] = obj_name
            ns['name'] = parts[-1]

            ns['objtype'] = doc.objtype
            ns['underline'] = len(name) * '='

            rendered = template.render(**ns)
            f.write(rendered)
        finally:
            f.close()
Ejemplo n.º 37
0
def generate_autosummary_docs(
    sources,
    output_dir=None,
    suffix=".rst",
    warn=_simple_warn,
    info=_simple_info,
    base_path=None,
    builder=None,
    template_dir=None,
):

    showed_sources = list(sorted(sources))
    if len(showed_sources) > 20:
        showed_sources = showed_sources[:10] + ["..."] + showed_sources[-10:]
    info("[autosummary] generating autosummary for: %s" % ", ".join(showed_sources))

    if output_dir:
        info("[autosummary] writing to %s" % output_dir)

    if base_path is not None:
        sources = [os.path.join(base_path, filename) for filename in sources]

    # create our own templating environment
    template_dirs = [os.path.join(package_dir, "ext", "autosummary", "templates")]
    if builder is not None:
        # allow the user to override the templates
        template_loader = BuiltinTemplateLoader()
        template_loader.init(builder, dirs=template_dirs)
    else:
        if template_dir:
            template_dirs.insert(0, template_dir)
        template_loader = FileSystemLoader(template_dirs)
    template_env = SandboxedEnvironment(loader=template_loader)

    # read
    items = find_autosummary_in_files(sources)

    # keep track of new files
    new_files = []

    # write
    for name, path, template_name in sorted(set(items), key=str):
        if path is None:
            # The corresponding autosummary:: directive did not have
            # a :toctree: option
            continue

        path = output_dir or os.path.abspath(path)
        ensuredir(path)

        try:
            name, obj, parent, mod_name = import_by_name(name)
        except ImportError as e:
            warn("[autosummary] failed to import %r: %s" % (name, e))
            continue

        fn = os.path.join(path, name + suffix)

        # skip it if it exists
        if os.path.isfile(fn):
            continue

        new_files.append(fn)

        with open(fn, "w") as f:
            doc = get_documenter(obj, parent)

            if template_name is not None:
                template = template_env.get_template(template_name)
            else:
                try:
                    template = template_env.get_template("autosummary/%s.rst" % doc.objtype)
                except TemplateNotFound:
                    template = template_env.get_template("autosummary/base.rst")

            def get_members(obj, typ, include_public=[]):
                items = []
                for name in dir(obj):
                    try:
                        documenter = get_documenter(safe_getattr(obj, name), obj)
                    except AttributeError:
                        continue
                    if documenter.objtype == typ:
                        items.append(name)
                public = [x for x in items if x in include_public or not x.startswith("_")]
                return public, items

            ns = {}

            if doc.objtype == "module":
                ns["members"] = dir(obj)
                ns["functions"], ns["all_functions"] = get_members(obj, "function")
                ns["classes"], ns["all_classes"] = get_members(obj, "class")
                ns["exceptions"], ns["all_exceptions"] = get_members(obj, "exception")
            elif doc.objtype == "class":
                ns["members"] = dir(obj)
                ns["methods"], ns["all_methods"] = get_members(obj, "method", ["__init__"])
                ns["attributes"], ns["all_attributes"] = get_members(obj, "attribute")

            parts = name.split(".")
            if doc.objtype in ("method", "attribute"):
                mod_name = ".".join(parts[:-2])
                cls_name = parts[-2]
                obj_name = ".".join(parts[-2:])
                ns["class"] = cls_name
            else:
                mod_name, obj_name = ".".join(parts[:-1]), parts[-1]

            ns["fullname"] = name
            ns["module"] = mod_name
            ns["objname"] = obj_name
            ns["name"] = parts[-1]

            ns["objtype"] = doc.objtype
            ns["underline"] = len(name) * "="

            rendered = template.render(**ns)
            f.write(rendered)

    # descend recursively to new files
    if new_files:
        generate_autosummary_docs(
            new_files,
            output_dir=output_dir,
            suffix=suffix,
            warn=warn,
            info=info,
            base_path=base_path,
            builder=builder,
            template_dir=template_dir,
        )
Ejemplo n.º 38
0
def generate_autosummary_content(name: str,
                                 obj: Any,
                                 parent: Any,
                                 template: AutosummaryRenderer,
                                 template_name: str,
                                 imported_members: bool,
                                 app: Any,
                                 recursive: bool,
                                 context: Dict,
                                 modname: str = None,
                                 qualname: str = None) -> str:
    doc = get_documenter(app, obj, parent)

    def skip_member(obj: Any, name: str, objtype: str) -> bool:
        try:
            return app.emit_firstresult('autodoc-skip-member', objtype, name,
                                        obj, False, {})
        except Exception as exc:
            logger.warning(__(
                'autosummary: failed to determine %r to be documented, '
                'the following exception was raised:\n%s'),
                           name,
                           exc,
                           type='autosummary')
            return False

    def get_class_members(obj: Any) -> Dict[str, Any]:
        members = sphinx.ext.autodoc.get_class_members(obj, [qualname],
                                                       safe_getattr)
        return {name: member.object for name, member in members.items()}

    def get_module_members(obj: Any) -> Dict[str, Any]:
        members = {}
        for name in members_of(obj, app.config):
            try:
                members[name] = safe_getattr(obj, name)
            except AttributeError:
                continue
        return members

    def get_all_members(obj: Any) -> Dict[str, Any]:
        if doc.objtype == "module":
            return get_module_members(obj)
        elif doc.objtype == "class":
            return get_class_members(obj)
        return {}

    def get_members(obj: Any,
                    types: Set[str],
                    include_public: List[str] = [],
                    imported: bool = True) -> Tuple[List[str], List[str]]:
        items: List[str] = []
        public: List[str] = []

        all_members = get_all_members(obj)
        for name, value in all_members.items():
            documenter = get_documenter(app, value, obj)
            if documenter.objtype in types:
                # skip imported members if expected
                if imported or getattr(value, '__module__',
                                       None) == obj.__name__:
                    skipped = skip_member(value, name, documenter.objtype)
                    if skipped is True:
                        pass
                    elif skipped is False:
                        # show the member forcedly
                        items.append(name)
                        public.append(name)
                    else:
                        items.append(name)
                        if name in include_public or not name.startswith('_'):
                            # considers member as public
                            public.append(name)
        return public, items

    def get_module_attrs(members: Any) -> Tuple[List[str], List[str]]:
        """Find module attributes with docstrings."""
        attrs, public = [], []
        try:
            analyzer = ModuleAnalyzer.for_module(name)
            attr_docs = analyzer.find_attr_docs()
            for namespace, attr_name in attr_docs:
                if namespace == '' and attr_name in members:
                    attrs.append(attr_name)
                    if not attr_name.startswith('_'):
                        public.append(attr_name)
        except PycodeError:
            pass  # give up if ModuleAnalyzer fails to parse code
        return public, attrs

    def get_modules(obj: Any) -> Tuple[List[str], List[str]]:
        items: List[str] = []
        for _, modname, _ispkg in pkgutil.iter_modules(obj.__path__):
            fullname = name + '.' + modname
            try:
                module = import_module(fullname)
                if module and hasattr(module, '__sphinx_mock__'):
                    continue
            except ImportError:
                pass

            items.append(fullname)
        public = [x for x in items if not x.split('.')[-1].startswith('_')]
        return public, items

    ns: Dict[str, Any] = {}
    ns.update(context)

    if doc.objtype == 'module':
        scanner = ModuleScanner(app, obj)
        ns['members'] = scanner.scan(imported_members)
        ns['functions'], ns['all_functions'] = \
            get_members(obj, {'function'}, imported=imported_members)
        ns['classes'], ns['all_classes'] = \
            get_members(obj, {'class'}, imported=imported_members)
        ns['exceptions'], ns['all_exceptions'] = \
            get_members(obj, {'exception'}, imported=imported_members)
        ns['attributes'], ns['all_attributes'] = \
            get_module_attrs(ns['members'])
        ispackage = hasattr(obj, '__path__')
        if ispackage and recursive:
            ns['modules'], ns['all_modules'] = get_modules(obj)
    elif doc.objtype == 'class':
        ns['members'] = dir(obj)
        ns['inherited_members'] = \
            set(dir(obj)) - set(obj.__dict__.keys())
        ns['methods'], ns['all_methods'] = \
            get_members(obj, {'method'}, ['__init__'])
        ns['attributes'], ns['all_attributes'] = \
            get_members(obj, {'attribute', 'property'})

    if modname is None or qualname is None:
        modname, qualname = split_full_qualified_name(name)

    if doc.objtype in ('method', 'attribute', 'property'):
        ns['class'] = qualname.rsplit(".", 1)[0]

    if doc.objtype in ('class', ):
        shortname = qualname
    else:
        shortname = qualname.rsplit(".", 1)[-1]

    ns['fullname'] = name
    ns['module'] = modname
    ns['objname'] = qualname
    ns['name'] = shortname

    ns['objtype'] = doc.objtype
    ns['underline'] = len(name) * '='

    if template_name:
        return template.render(template_name, ns)
    else:
        return template.render(doc.objtype, ns)
Ejemplo n.º 39
0
def generate_autosummary_docs(sources,
                              output_dir=None,
                              suffix='.rst',
                              warn=_simple_warn,
                              info=_simple_info,
                              base_path=None,
                              builder=None,
                              template_dir=None,
                              app=None):
    showed_sources = list(sorted(sources))
    if len(showed_sources) > 20:
        showed_sources = showed_sources[:10] + ['...'] + showed_sources[-10:]
    info('[autosummary] generating autosummary for: %s' %
         ', '.join(showed_sources))

    if output_dir:
        info('[autosummary] writing to %s' % output_dir)

    if base_path is not None:
        sources = [osp.join(base_path, filename) for filename in sources]

    # create our own templating environment
    template_dirs = [osp.join(package_dir, 'ext', 'autosummary', 'templates')]
    if builder is not None:
        # allow the user to override the templates
        template_loader = BuiltinTemplateLoader()
        template_loader.init(builder, dirs=template_dirs)
    else:
        if template_dir:
            template_dirs.insert(0, template_dir)
        template_loader = FileSystemLoader(template_dirs)
    template_env = SandboxedEnvironment(loader=template_loader)

    # read
    items = find_autosummary_in_files(sources)

    # remove possible duplicates
    items = list(dict([(item, True) for item in items]).keys())

    # keep track of new files
    new_files = []

    # write
    # noinspection PyTypeChecker
    for name, path, template_name in sorted(items, key=str):
        if path is None:
            # The corresponding autosummary:: directive did not have
            # a :toctree: option
            continue

        path = output_dir or osp.abspath(path)
        ensuredir(path)

        try:
            name, obj, parent, mod_name = import_by_name(name)
        except ImportError as e:
            warn('[autosummary] failed to import %r: %s' % (name, e))
            continue

        fn = osp.join(path, name + suffix)

        # skip it if it exists
        if osp.isfile(fn):
            continue

        new_files.append(fn)

        f = open(fn, 'w')

        try:
            try:
                doc = get_documenter(app, obj, parent)
            except TypeError:
                doc = get_documenter(obj, parent)

            if template_name is not None:
                template = template_env.get_template(template_name)
            else:
                try:
                    template = template_env.get_template('autosummary/%s.rst' %
                                                         doc.objtype)
                except TemplateNotFound:
                    template = template_env.get_template(
                        'autosummary/base.rst')

            ns = {}

            if doc.objtype == 'module':
                ns['members'] = dir(obj)
                ns['functions'], ns['all_functions'] = \
                    get_members(app, obj, 'function')
                ns['classes'], ns['all_classes'] = \
                    get_members(app, obj, 'class')
                ns['exceptions'], ns['all_exceptions'] = \
                    get_members(app, obj, 'exception')
                ns['data'], ns['all_data'] = \
                    get_members(app, obj, 'data', imported=True)

                ns['data'] = ', '.join(ns['data'])
                ns['all_data'] = ', '.join(ns['all_data'])

                ns['dispatchers'], ns['all_dispatchers'] = \
                    get_members(app, obj, 'dispatcher', imported=True)
            elif doc.objtype == 'class':
                ns['members'] = dir(obj)
                ns['methods'], ns['all_methods'] = \
                    get_members(app, obj, 'method', ['__init__'], True)
                ns['attributes'], ns['all_attributes'] = \
                    get_members(app, obj, 'attribute')

            parts = name.split('.')
            if doc.objtype in ('method', 'attribute'):
                mod_name = '.'.join(parts[:-2])
                cls_name = parts[-2]
                obj_name = '.'.join(parts[-2:])
                ns['class'] = cls_name
            else:
                mod_name, obj_name = '.'.join(parts[:-1]), parts[-1]

            ns['fullname'] = name
            ns['module'] = mod_name
            ns['objname'] = obj_name
            ns['name'] = parts[-1]

            ns['objtype'] = doc.objtype
            ns['underline'] = len(name) * '='

            rendered = template.render(**ns)
            f.write(rendered)
        finally:
            f.close()

    # descend recursively to new files
    if new_files:
        generate_autosummary_docs(new_files,
                                  output_dir=output_dir,
                                  suffix=suffix,
                                  warn=warn,
                                  info=info,
                                  base_path=base_path,
                                  builder=builder,
                                  template_dir=template_dir,
                                  app=app)
Ejemplo n.º 40
0
    def get_items(self, names):
        """Try to import the given names, and return a list of
        ``[(name, signature, summary_string, real_name), ...]``.
        """
        from sphinx.ext.autosummary import (get_import_prefixes_from_env,
            import_by_name, get_documenter, mangle_signature)

        env = self.state.document.settings.env

        prefixes = get_import_prefixes_from_env(env)

        items = []

        max_item_chars = 50

        for name in names:
            display_name = name
            if name.startswith('~'):
                name = name[1:]
                display_name = name.split('.')[-1]

            try:
                import_by_name_values = import_by_name(name, prefixes=prefixes)
            except ImportError:
                self.warn('[astropyautosummary] failed to import %s' % name)
                items.append((name, '', '', name))
                continue

            # to accommodate Sphinx v1.2.2 and v1.2.3
            if len(import_by_name_values) == 3:
                real_name, obj, parent = import_by_name_values
            elif len(import_by_name_values) == 4:
                real_name, obj, parent, module_name = import_by_name_values

            # NB. using real_name here is important, since Documenters
            #     handle module prefixes slightly differently
            documenter = get_documenter(obj, parent)(self, real_name)
            if not documenter.parse_name():
                self.warn('[astropyautosummary] failed to parse name %s' % real_name)
                items.append((display_name, '', '', real_name))
                continue
            if not documenter.import_object():
                self.warn('[astropyautosummary] failed to import object %s' % real_name)
                items.append((display_name, '', '', real_name))
                continue

            # -- Grab the signature

            sig = documenter.format_signature()
            if not sig:
                sig = ''
            else:
                max_chars = max(10, max_item_chars - len(display_name))
                sig = mangle_signature(sig, max_chars=max_chars)
                sig = sig.replace('*', r'\*')

            # -- Grab the summary

            doc = list(documenter.process_doc(documenter.get_doc()))

            while doc and not doc[0].strip():
                doc.pop(0)
            m = _itemsummrex.search(" ".join(doc).strip())
            if m:
                summary = m.group(1).strip()
            elif doc:
                summary = doc[0].strip()
            else:
                summary = ''

            items.append((display_name, sig, summary, real_name))

        return items
Ejemplo n.º 41
0
    def get_items(self, names):
        """Try to import the given names, and return a list of
        ``[(name, signature, summary_string, real_name), ...]``.
        """
        env = self.state.document.settings.env

        prefixes = get_import_prefixes_from_env(env)

        items = []

        max_item_chars = 50

        for name in names:
            display_name = name
            if name.startswith('~'):
                name = name[1:]
                display_name = name.split('.')[-1]

            try:
                real_name, obj, parent = import_by_name(name,
                                                        prefixes=prefixes)
            except ImportError:
                self.warn('failed to import %s' % name)
                items.append((name, '', '', name))
                continue

            # NB. using real_name here is important, since Documenters
            #     handle module prefixes slightly differently
            documenter = get_documenter(obj, parent)(self, real_name)
            if not documenter.parse_name():
                self.warn('failed to parse name %s' % real_name)
                items.append((display_name, '', '', real_name))
                continue
            if not documenter.import_object():
                self.warn('failed to import object %s' % real_name)
                items.append((display_name, '', '', real_name))
                continue
            display_name = documenter.format_name()

            # -- Grab the signature

            sig = documenter.format_signature()
            if not sig:
                sig = ''
            else:
                max_chars = max(10, max_item_chars - len(display_name))
                sig = mangle_signature(sig, max_chars=max_chars)
                sig = sig.replace('*', r'\*')

            # -- Grab the summary

            doc = list(documenter.process_doc(documenter.get_doc()))

            while doc and not doc[0].strip():
                doc.pop(0)
            m = re.search(r"^([A-Z][^A-Z]*?\.\s)", " ".join(doc).strip())
            if m:
                summary = m.group(1).strip()
            elif doc:
                summary = doc[0].strip()
            else:
                summary = ''

            items.append((display_name, sig, summary, real_name))

        return items
Ejemplo n.º 42
0
def generate_autosummary_content(name: str, obj: Any, parent: Any,
                                 template: AutosummaryRenderer,
                                 template_name: str, imported_members: bool,
                                 app: Any) -> str:
    doc = get_documenter(app, obj, parent)

    if template_name is None:
        template_name = 'autosummary/%s.rst' % doc.objtype
        if not template.exists(template_name):
            template_name = 'autosummary/base.rst'

    def get_members(obj: Any,
                    types: Set[str],
                    include_public: List[str] = [],
                    imported: bool = True) -> Tuple[List[str], List[str]]:
        items = []  # type: List[str]
        for name in dir(obj):
            try:
                value = safe_getattr(obj, name)
            except AttributeError:
                continue
            documenter = get_documenter(app, value, obj)
            if documenter.objtype in types:
                if imported or getattr(value, '__module__',
                                       None) == obj.__name__:
                    # skip imported members if expected
                    items.append(name)
        public = [
            x for x in items if x in include_public or not x.startswith('_')
        ]
        return public, items

    ns = {}  # type: Dict[str, Any]

    if doc.objtype == 'module':
        ns['members'] = dir(obj)
        ns['functions'], ns['all_functions'] = \
            get_members(obj, {'function'}, imported=imported_members)
        ns['classes'], ns['all_classes'] = \
            get_members(obj, {'class'}, imported=imported_members)
        ns['exceptions'], ns['all_exceptions'] = \
            get_members(obj, {'exception'}, imported=imported_members)
    elif doc.objtype == 'class':
        ns['members'] = dir(obj)
        ns['inherited_members'] = \
            set(dir(obj)) - set(obj.__dict__.keys())
        ns['methods'], ns['all_methods'] = \
            get_members(obj, {'method'}, ['__init__'])
        ns['attributes'], ns['all_attributes'] = \
            get_members(obj, {'attribute', 'property'})

    parts = name.split('.')
    if doc.objtype in ('method', 'attribute', 'property'):
        mod_name = '.'.join(parts[:-2])
        cls_name = parts[-2]
        obj_name = '.'.join(parts[-2:])
        ns['class'] = cls_name
    else:
        mod_name, obj_name = '.'.join(parts[:-1]), parts[-1]

    ns['fullname'] = name
    ns['module'] = mod_name
    ns['objname'] = obj_name
    ns['name'] = parts[-1]

    ns['objtype'] = doc.objtype
    ns['underline'] = len(name) * '='

    return template.render(template_name, ns)
Ejemplo n.º 43
0
def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
                              warn=_simple_warn, info=_simple_info,
                              base_path=None, builder=None, template_dir=None,
                              imported_members=False):
    # type: (List[unicode], unicode, unicode, Callable, Callable, unicode, Builder, unicode, bool) -> None  # NOQA

    showed_sources = list(sorted(sources))
    if len(showed_sources) > 20:
        showed_sources = showed_sources[:10] + ['...'] + showed_sources[-10:]
    info('[autosummary] generating autosummary for: %s' %
         ', '.join(showed_sources))

    if output_dir:
        info('[autosummary] writing to %s' % output_dir)

    if base_path is not None:
        sources = [os.path.join(base_path, filename) for filename in sources]

    # create our own templating environment
    template_dirs = None  # type: List[unicode]
    template_dirs = [os.path.join(package_dir, 'ext',
                                  'autosummary', 'templates')]

    template_loader = None  # type: BaseLoader
    if builder is not None:
        # allow the user to override the templates
        template_loader = BuiltinTemplateLoader()
        template_loader.init(builder, dirs=template_dirs)
    else:
        if template_dir:
            template_dirs.insert(0, template_dir)
        template_loader = FileSystemLoader(template_dirs)  # type: ignore
    template_env = SandboxedEnvironment(loader=template_loader)
    template_env.filters['underline'] = _underline

    # replace the builtin html filters
    template_env.filters['escape'] = rst_escape
    template_env.filters['e'] = rst_escape

    # read
    items = find_autosummary_in_files(sources)

    # keep track of new files
    new_files = []

    # write
    for name, path, template_name in sorted(set(items), key=str):
        if path is None:
            # The corresponding autosummary:: directive did not have
            # a :toctree: option
            continue

        path = output_dir or os.path.abspath(path)
        ensuredir(path)

        try:
            name, obj, parent, mod_name = import_by_name(name)
        except ImportError as e:
            warn('[autosummary] failed to import %r: %s' % (name, e))
            continue

        fn = os.path.join(path, name + suffix)

        # skip it if it exists
        if os.path.isfile(fn):
            continue

        new_files.append(fn)

        with open(fn, 'w') as f:
            doc = get_documenter(obj, parent)

            if template_name is not None:
                template = template_env.get_template(template_name)
            else:
                try:
                    template = template_env.get_template('autosummary/%s.rst'
                                                         % doc.objtype)
                except TemplateNotFound:
                    template = template_env.get_template('autosummary/base.rst')

            def get_members(obj, typ, include_public=[], imported=False):
                # type: (Any, unicode, List[unicode], bool) -> Tuple[List[unicode], List[unicode]]  # NOQA
                items = []  # type: List[unicode]
                for name in dir(obj):
                    try:
                        value = safe_getattr(obj, name)
                    except AttributeError:
                        continue
                    documenter = get_documenter(value, obj)
                    if documenter.objtype == typ:
                        if typ == 'method':
                            items.append(name)
                        elif imported or getattr(value, '__module__', None) == obj.__name__:
                            # skip imported members if expected
                            items.append(name)
                public = [x for x in items
                          if x in include_public or not x.startswith('_')]
                return public, items

            ns = {}  # type: Dict[unicode, Any]

            if doc.objtype == 'module':
                ns['members'] = dir(obj)
                ns['functions'], ns['all_functions'] = \
                    get_members(obj, 'function', imported=imported_members)
                ns['classes'], ns['all_classes'] = \
                    get_members(obj, 'class', imported=imported_members)
                ns['exceptions'], ns['all_exceptions'] = \
                    get_members(obj, 'exception', imported=imported_members)
            elif doc.objtype == 'class':
                ns['members'] = dir(obj)
                ns['methods'], ns['all_methods'] = \
                    get_members(obj, 'method', ['__init__'], imported=imported_members)
                ns['attributes'], ns['all_attributes'] = \
                    get_members(obj, 'attribute', imported=imported_members)

            parts = name.split('.')
            if doc.objtype in ('method', 'attribute'):
                mod_name = '.'.join(parts[:-2])
                cls_name = parts[-2]
                obj_name = '.'.join(parts[-2:])
                ns['class'] = cls_name
            else:
                mod_name, obj_name = '.'.join(parts[:-1]), parts[-1]

            ns['fullname'] = name
            ns['module'] = mod_name
            ns['objname'] = obj_name
            ns['name'] = parts[-1]

            ns['objtype'] = doc.objtype
            ns['underline'] = len(name) * '='

            rendered = template.render(**ns)
            f.write(rendered)  # type: ignore

    # descend recursively to new files
    if new_files:
        generate_autosummary_docs(new_files, output_dir=output_dir,
                                  suffix=suffix, warn=warn, info=info,
                                  base_path=base_path, builder=builder,
                                  template_dir=template_dir)
Ejemplo n.º 44
0
def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
                              warn=_simple_warn, info=_simple_info,
                              base_path=None, builder=None, template_dir=None):

    showed_sources = list(sorted(sources))
    if len(showed_sources) > 20:
        showed_sources = showed_sources[:10] + ['...'] + showed_sources[-10:]
    info('[autosummary] generating autosummary for: %s' %
         ', '.join(showed_sources))

    if output_dir:
        info('[autosummary] writing to %s' % output_dir)

    if base_path is not None:
        sources = [os.path.join(base_path, filename) for filename in sources]

    # create our own templating environment
    template_dirs = [os.path.join(package_dir, 'ext',
                                  'autosummary', 'templates')]
    if builder is not None:
        # allow the user to override the templates
        template_loader = BuiltinTemplateLoader()
        template_loader.init(builder, dirs=template_dirs)
    else:
        if template_dir:
            template_dirs.insert(0, template_dir)
        template_loader = FileSystemLoader(template_dirs)
    template_env = SandboxedEnvironment(loader=template_loader)

    # read
    items = find_autosummary_in_files(sources)

    # remove possible duplicates
    items = list(dict([(item, True) for item in items]).keys())

    # keep track of new files
    new_files = []

    # write
    for name, path, template_name in sorted(items, key=str):
        if path is None:
            # The corresponding autosummary:: directive did not have
            # a :toctree: option
            continue

        path = output_dir or os.path.abspath(path)
        ensuredir(path)

        try:
            name, obj, parent = import_by_name(name)
        except ImportError as e:
            warn('[autosummary] failed to import %r: %s' % (name, e))
            continue

        fn = os.path.join(path, name + suffix)

        # skip it if it exists
        if os.path.isfile(fn):
            continue

        new_files.append(fn)

        f = open(fn, 'w')

        try:
            doc = get_documenter(obj, parent)

            if template_name is not None:
                template = template_env.get_template(template_name)
            else:
                try:
                    template = template_env.get_template('autosummary/%s.rst'
                                                         % doc.objtype)
                except TemplateNotFound:
                    template = template_env.get_template('autosummary/base.rst')

            def get_members(obj, typ, include_public=[]):
                items = []
                for name in dir(obj):
                    try:
                        documenter = get_documenter(safe_getattr(obj, name),
                                                    obj)
                    except AttributeError:
                        continue
                    if documenter.objtype == typ:
                        items.append(name)
                public = [x for x in items
                          if x in include_public or not x.startswith('_')]
                return public, items

            ns = {}

            if doc.objtype == 'module':
                ns['members'] = dir(obj)
                ns['functions'], ns['all_functions'] = \
                                   get_members(obj, 'function')
                ns['classes'], ns['all_classes'] = \
                                 get_members(obj, 'class')
                ns['exceptions'], ns['all_exceptions'] = \
                                   get_members(obj, 'exception')
            elif doc.objtype == 'class':
                ns['members'] = dir(obj)
                ns['methods'], ns['all_methods'] = \
                                 get_members(obj, 'method', ['__init__'])
                ns['attributes'], ns['all_attributes'] = \
                                 get_members(obj, 'attribute')

            parts = name.split('.')
            if doc.objtype in ('method', 'attribute'):
                mod_name = '.'.join(parts[:-2])
                cls_name = parts[-2]
                obj_name = '.'.join(parts[-2:])
                ns['class'] = cls_name
            else:
                mod_name, obj_name = '.'.join(parts[:-1]), parts[-1]

            ns['fullname'] = name
            ns['module'] = mod_name
            ns['objname'] = obj_name
            ns['name'] = parts[-1]

            ns['objtype'] = doc.objtype
            ns['underline'] = len(name) * '='

            rendered = template.render(**ns)
            f.write(rendered)
        finally:
            f.close()

    # descend recursively to new files
    if new_files:
        generate_autosummary_docs(new_files, output_dir=output_dir,
                                  suffix=suffix, warn=warn, info=info,
                                  base_path=base_path, builder=builder,
                                  template_dir=template_dir)
Ejemplo n.º 45
0
 def get_object_type(self, name: str, value: Any) -> str:
     return get_documenter(self.app, value, self.object).objtype
Ejemplo n.º 46
0
def generate_automodsumm_docs(lines, srcfn, suffix='.rst', warn=None,
                              info=None, base_path=None, builder=None,
                              template_dir=None):
    """
    This function is adapted from
    `sphinx.ext.autosummary.generate.generate_autosummmary_docs` to
    generate source for the automodsumm directives that should be
    autosummarized. Unlike generate_autosummary_docs, this function is
    called one file at a time.
    """

    from sphinx.jinja2glue import BuiltinTemplateLoader
    from sphinx.ext.autosummary import import_by_name, get_documenter
    from sphinx.ext.autosummary.generate import (find_autosummary_in_lines,
                                                 _simple_info, _simple_warn)
    from sphinx.util.osutil import ensuredir
    from sphinx.util.inspect import safe_getattr
    from jinja2 import FileSystemLoader, TemplateNotFound
    from jinja2.sandbox import SandboxedEnvironment

    if info is None:
        info = _simple_info
    if warn is None:
        warn = _simple_warn

    #info('[automodsumm] generating automodsumm for: ' + srcfn)

    # Create our own templating environment - here we use Astropy's
    # templates rather than the default autosummary templates, in order to
    # allow docstrings to be shown for methods.
    template_dirs = [os.path.join(os.path.dirname(__file__), 'templates'),
                     os.path.join(base_path, '_templates')]
    if builder is not None:
        # allow the user to override the templates
        template_loader = BuiltinTemplateLoader()
        template_loader.init(builder, dirs=template_dirs)
    else:
        if template_dir:
            template_dirs.insert(0, template_dir)
        template_loader = FileSystemLoader(template_dirs)
    template_env = SandboxedEnvironment(loader=template_loader)

    # read
    #items = find_autosummary_in_files(sources)
    items = find_autosummary_in_lines(lines, filename=srcfn)
    if len(items) > 0:
        msg = '[automodsumm] {1}: found {0} automodsumm entries to generate'
        info(msg.format(len(items), srcfn))

#    gennms = [item[0] for item in items]
#    if len(gennms) > 20:
#        gennms = gennms[:10] + ['...'] + gennms[-10:]
#    info('[automodsumm] generating autosummary for: ' + ', '.join(gennms))

    # remove possible duplicates
    items = dict([(item, True) for item in items]).keys()

    # keep track of new files
    new_files = []

    # write
    for name, path, template_name in sorted(items):
        if path is None:
            # The corresponding autosummary:: directive did not have
            # a :toctree: option
            continue

        path = os.path.abspath(path)
        ensuredir(path)

        try:
            import_by_name_values = import_by_name(name)
        except ImportError as e:
            warn('[automodsumm] failed to import %r: %s' % (name, e))
            continue

        # if block to accommodate Sphinx's v1.2.2 and v1.2.3 respectively
        if len(import_by_name_values) == 3:
            name, obj, parent = import_by_name_values
        elif len(import_by_name_values) == 4:
            name, obj, parent, module_name = import_by_name_values

        fn = os.path.join(path, name + suffix)

        # skip it if it exists
        if os.path.isfile(fn):
            continue

        new_files.append(fn)

        f = open(fn, 'w')

        try:
            doc = get_documenter(obj, parent)

            if template_name is not None:
                template = template_env.get_template(template_name)
            else:
                tmplstr = 'autosummary/%s.rst'
                try:
                    template = template_env.get_template(tmplstr % doc.objtype)
                except TemplateNotFound:
                    template = template_env.get_template(tmplstr % 'base')

            def get_members_mod(obj, typ, include_public=[]):
                """
                typ = None -> all
                """
                items = []
                for name in dir(obj):
                    try:
                        documenter = get_documenter(safe_getattr(obj, name),
                                                    obj)
                    except AttributeError:
                        continue
                    if typ is None or documenter.objtype == typ:
                        items.append(name)
                public = [x for x in items
                          if x in include_public or not x.startswith('_')]
                return public, items

            def get_members_class(obj, typ, include_public=[],
                                  include_base=False):
                """
                typ = None -> all
                include_base -> include attrs that are from a base class
                """
                items = []

                # using dir gets all of the attributes, including the elements
                # from the base class, otherwise use __slots__ or __dict__
                if include_base:
                    names = dir(obj)
                else:
                    if hasattr(obj, '__slots__'):
                        names = tuple(getattr(obj, '__slots__'))
                    else:
                        names = getattr(obj, '__dict__').keys()

                for name in names:
                    try:
                        documenter = get_documenter(safe_getattr(obj, name),
                                                    obj)
                    except AttributeError:
                        continue
                    if typ is None or documenter.objtype == typ:
                        items.append(name)
                public = [x for x in items
                          if x in include_public or not x.startswith('_')]
                return public, items

            ns = {}

            if doc.objtype == 'module':
                ns['members'] = get_members_mod(obj, None)
                ns['functions'], ns['all_functions'] = \
                                   get_members_mod(obj, 'function')
                ns['classes'], ns['all_classes'] = \
                                 get_members_mod(obj, 'class')
                ns['exceptions'], ns['all_exceptions'] = \
                                   get_members_mod(obj, 'exception')
            elif doc.objtype == 'class':
                api_class_methods = ['__init__', '__call__']
                ns['members'] = get_members_class(obj, None)
                ns['methods'], ns['all_methods'] = \
                                 get_members_class(obj, 'method', api_class_methods)
                ns['attributes'], ns['all_attributes'] = \
                                 get_members_class(obj, 'attribute')
                ns['methods'].sort()
                ns['attributes'].sort()

            parts = name.split('.')
            if doc.objtype in ('method', 'attribute'):
                mod_name = '.'.join(parts[:-2])
                cls_name = parts[-2]
                obj_name = '.'.join(parts[-2:])
                ns['class'] = cls_name
            else:
                mod_name, obj_name = '.'.join(parts[:-1]), parts[-1]

            ns['fullname'] = name
            ns['module'] = mod_name
            ns['objname'] = obj_name
            ns['name'] = parts[-1]

            ns['objtype'] = doc.objtype
            ns['underline'] = len(name) * '='

            # We now check whether a file for reference footnotes exists for
            # the module being documented. We first check if the
            # current module is a file or a directory, as this will give a
            # different path for the reference file. For example, if
            # documenting astropy.wcs then the reference file is at
            # ../wcs/references.txt, while if we are documenting
            # astropy.config.logging_helper (which is at
            # astropy/config/logging_helper.py) then the reference file is set
            # to ../config/references.txt
            if '.' in mod_name:
                mod_name_dir = mod_name.replace('.', '/').split('/', 1)[1]
            else:
                mod_name_dir = mod_name
            if not os.path.isdir(os.path.join(base_path, mod_name_dir)) \
               and os.path.isdir(os.path.join(base_path, mod_name_dir.rsplit('/', 1)[0])):
                mod_name_dir = mod_name_dir.rsplit('/', 1)[0]

            # We then have to check whether it exists, and if so, we pass it
            # to the template.
            if os.path.exists(os.path.join(base_path, mod_name_dir, 'references.txt')):
                # An important subtlety here is that the path we pass in has
                # to be relative to the file being generated, so we have to
                # figure out the right number of '..'s
                ndirsback = path.replace(base_path, '').count('/')
                ref_file_rel_segments = ['..'] * ndirsback
                ref_file_rel_segments.append(mod_name_dir)
                ref_file_rel_segments.append('references.txt')
                ns['referencefile'] = os.path.join(*ref_file_rel_segments)

            rendered = template.render(**ns)
            f.write(rendered)
        finally:
            f.close()
Ejemplo n.º 47
0
def generate_autosummary_docs(sources,
                              output_dir=None,
                              suffix='.rst',
                              warn=_simple_warn,
                              info=_simple_info,
                              base_path=None,
                              builder=None,
                              template_dir=None):

    showed_sources = list(sorted(sources))
    if len(showed_sources) > 20:
        showed_sources = showed_sources[:10] + ['...'] + showed_sources[-10:]
    info('[autosummary] generating autosummary for: %s' %
         ', '.join(showed_sources))

    if output_dir:
        info('[autosummary] writing to %s' % output_dir)

    if base_path is not None:
        sources = [os.path.join(base_path, filename) for filename in sources]

    # create our own templating environment
    template_dirs = [
        os.path.join(package_dir, 'ext', 'autosummary', 'templates')
    ]
    if builder is not None:
        # allow the user to override the templates
        template_loader = BuiltinTemplateLoader()
        template_loader.init(builder, dirs=template_dirs)
    else:
        if template_dir:
            template_dirs.insert(0, template_dir)
        template_loader = FileSystemLoader(template_dirs)
    template_env = SandboxedEnvironment(loader=template_loader)

    # read
    items = find_autosummary_in_files(sources)

    # keep track of new files
    new_files = []

    # write
    for name, path, template_name in sorted(set(items), key=str):
        if path is None:
            # The corresponding autosummary:: directive did not have
            # a :toctree: option
            continue

        path = output_dir or os.path.abspath(path)
        ensuredir(path)

        try:
            name, obj, parent, mod_name = import_by_name(name)
        except ImportError as e:
            warn('[autosummary] failed to import %r: %s' % (name, e))
            continue

        fn = os.path.join(path, name + suffix)

        # skip it if it exists
        if os.path.isfile(fn):
            continue

        new_files.append(fn)

        with open(fn, 'w') as f:
            doc = get_documenter(obj, parent)

            if template_name is not None:
                template = template_env.get_template(template_name)
            else:
                try:
                    template = template_env.get_template('autosummary/%s.rst' %
                                                         doc.objtype)
                except TemplateNotFound:
                    template = template_env.get_template(
                        'autosummary/base.rst')

            def get_members(obj, typ, include_public=[], imported=False):
                items = []
                for name in dir(obj):
                    try:
                        obj_name = safe_getattr(obj, name)
                        documenter = get_documenter(obj_name, obj)
                    except AttributeError:
                        continue
                    if documenter.objtype == typ:
                        try:
                            cond = (imported
                                    or obj_name.__module__ == obj.__name__)
                        except AttributeError:
                            cond = True
                        if cond:
                            items.append(name)
                public = [
                    x for x in items
                    if x in include_public or not x.startswith('_')
                ]
                return public, items

            ns = {}

            if doc.objtype == 'module':
                ns['members'] = dir(obj)
                ns['functions'], ns['all_functions'] = \
                    get_members(obj, 'function')
                ns['classes'], ns['all_classes'] = \
                    get_members(obj, 'class')
                ns['exceptions'], ns['all_exceptions'] = \
                    get_members(obj, 'exception')
            elif doc.objtype == 'class':
                ns['members'] = dir(obj)
                ns['methods'], ns['all_methods'] = \
                    get_members(obj, 'method', ['__init__'])
                ns['attributes'], ns['all_attributes'] = \
                    get_members(obj, 'attribute')

            parts = name.split('.')
            if doc.objtype in ('method', 'attribute'):
                mod_name = '.'.join(parts[:-2])
                cls_name = parts[-2]
                obj_name = '.'.join(parts[-2:])
                ns['class'] = cls_name
            else:
                mod_name, obj_name = '.'.join(parts[:-1]), parts[-1]

            ns['fullname'] = name
            ns['module'] = mod_name
            ns['objname'] = obj_name
            ns['name'] = parts[-1]

            ns['objtype'] = doc.objtype
            ns['underline'] = len(name) * '='

            rendered = template.render(**ns)
            f.write(rendered)

    # descend recursively to new files
    if new_files:
        generate_autosummary_docs(new_files,
                                  output_dir=output_dir,
                                  suffix=suffix,
                                  warn=warn,
                                  info=info,
                                  base_path=base_path,
                                  builder=builder,
                                  template_dir=template_dir)
Ejemplo n.º 48
0
def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
                              warn=_simple_warn, info=_simple_info,
                              base_path=None, builder=None, template_dir=None,
                              imported_members=False, app=None):
    # type: (List[str], str, str, Callable, Callable, str, Builder, str, bool, Any) -> None

    showed_sources = list(sorted(sources))
    if len(showed_sources) > 20:
        showed_sources = showed_sources[:10] + ['...'] + showed_sources[-10:]
    info(__('[autosummary] generating autosummary for: %s') %
         ', '.join(showed_sources))

    if output_dir:
        info(__('[autosummary] writing to %s') % output_dir)

    if base_path is not None:
        sources = [os.path.join(base_path, filename) for filename in sources]

    template = AutosummaryRenderer(builder, template_dir)

    # read
    items = find_autosummary_in_files(sources)

    # keep track of new files
    new_files = []

    # write
    for name, path, template_name in sorted(set(items), key=str):
        if path is None:
            # The corresponding autosummary:: directive did not have
            # a :toctree: option
            continue

        path = output_dir or os.path.abspath(path)
        ensuredir(path)

        try:
            name, obj, parent, mod_name = import_by_name(name)
        except ImportError as e:
            warn('[autosummary] failed to import %r: %s' % (name, e))
            continue

        fn = os.path.join(path, name + suffix)

        # skip it if it exists
        if os.path.isfile(fn):
            continue

        new_files.append(fn)

        with open(fn, 'w') as f:
            doc = get_documenter(app, obj, parent)

            if template_name is None:
                template_name = 'autosummary/%s.rst' % doc.objtype
                if not template.exists(template_name):
                    template_name = 'autosummary/base.rst'

            def get_members(obj, types, include_public=[], imported=True):
                # type: (Any, Set[str], List[str], bool) -> Tuple[List[str], List[str]]  # NOQA
                items = []  # type: List[str]
                for name in dir(obj):
                    try:
                        value = safe_getattr(obj, name)
                    except AttributeError:
                        continue
                    documenter = get_documenter(app, value, obj)
                    if documenter.objtype in types:
                        if imported or getattr(value, '__module__', None) == obj.__name__:
                            # skip imported members if expected
                            items.append(name)
                public = [x for x in items
                          if x in include_public or not x.startswith('_')]
                return public, items

            ns = {}  # type: Dict[str, Any]

            if doc.objtype == 'module':
                ns['members'] = dir(obj)
                ns['functions'], ns['all_functions'] = \
                    get_members(obj, {'function'}, imported=imported_members)
                ns['classes'], ns['all_classes'] = \
                    get_members(obj, {'class'}, imported=imported_members)
                ns['exceptions'], ns['all_exceptions'] = \
                    get_members(obj, {'exception'}, imported=imported_members)
            elif doc.objtype == 'class':
                ns['members'] = dir(obj)
                ns['inherited_members'] = \
                    set(dir(obj)) - set(obj.__dict__.keys())
                ns['methods'], ns['all_methods'] = \
                    get_members(obj, {'method'}, ['__init__'])
                ns['attributes'], ns['all_attributes'] = \
                    get_members(obj, {'attribute', 'property'})

            parts = name.split('.')
            if doc.objtype in ('method', 'attribute', 'property'):
                mod_name = '.'.join(parts[:-2])
                cls_name = parts[-2]
                obj_name = '.'.join(parts[-2:])
                ns['class'] = cls_name
            else:
                mod_name, obj_name = '.'.join(parts[:-1]), parts[-1]

            ns['fullname'] = name
            ns['module'] = mod_name
            ns['objname'] = obj_name
            ns['name'] = parts[-1]

            ns['objtype'] = doc.objtype
            ns['underline'] = len(name) * '='

            rendered = template.render(template_name, ns)
            f.write(rendered)

    # descend recursively to new files
    if new_files:
        generate_autosummary_docs(new_files, output_dir=output_dir,
                                  suffix=suffix, warn=warn, info=info,
                                  base_path=base_path, builder=builder,
                                  template_dir=template_dir, app=app)