def get_documenter(app: Sphinx, obj: Any, parent: Any) -> "Type[Documenter]": """Get an autodoc.Documenter class suitable for documenting the given object. *obj* is the Python object to be documented, and *parent* is an another Python object (e.g. a module or a class) to which *obj* belongs to. """ from sphinx.ext.autodoc import DataDocumenter, ModuleDocumenter if inspect.ismodule(obj): # ModuleDocumenter.can_document_member always returns False return ModuleDocumenter # Construct a fake documenter for *parent* if parent is not None: parent_doc_cls = get_documenter(app, parent, None) else: parent_doc_cls = ModuleDocumenter if hasattr(parent, '__name__'): parent_doc = parent_doc_cls(FakeDirective(), parent.__name__) else: parent_doc = parent_doc_cls(FakeDirective(), "") # Get the corrent documenter class for *obj* classes = [cls for cls in get_documenters(app).values() if cls.can_document_member(obj, '', False, parent_doc)] if classes: classes.sort(key=lambda cls: cls.priority) return classes[-1] else: return DataDocumenter
def setup(app): """setup function for using this module as a sphinx extension""" app.setup_extension('sphinx.ext.autosummary') app.setup_extension('sphinx.ext.autodoc') # make sure to allow inheritance when registering new documenters if sphinx_version < [1, 7]: registry = AutodocRegistry._registry else: registry = get_documenters(app) for cls in [ AutoSummClassDocumenter, AutoSummModuleDocumenter, CallableAttributeDocumenter, NoDataDataDocumenter, NoDataAttributeDocumenter ]: if not issubclass(registry.get(cls.objtype), cls): try: # we use add_documenter because this does not add a new # directive app.add_documenter(cls) except AttributeError: app.add_autodocumenter(cls) # directives app.add_directive('automodule', AutoSummDirective, override=True) app.add_directive('autoclass', AutoSummDirective, override=True) # group event app.add_event('autodocsumm-grouper') # config value app.add_config_value('autodata_content', 'class', True) app.add_config_value('document_data', True, True) app.add_config_value('not_document_data', [], True) return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
def setup(app): """setup function for using this module as a sphinx extension""" app.setup_extension('sphinx.ext.autosummary') app.setup_extension('sphinx.ext.autodoc') app.add_directive('autoclasssumm', AutoDocSummDirective) app.add_directive('automodulesumm', AutoDocSummDirective) AUTODOC_DEFAULT_OPTIONS.extend( [option for option in AutoSummModuleDocumenter.option_spec if option not in AUTODOC_DEFAULT_OPTIONS]) AUTODOC_DEFAULT_OPTIONS.extend( [option for option in AutoSummClassDocumenter.option_spec if option not in AUTODOC_DEFAULT_OPTIONS]) # make sure to allow inheritance when registering new documenters registry = get_documenters(app) for cls in [AutoSummClassDocumenter, AutoSummModuleDocumenter, CallableAttributeDocumenter, NoDataDataDocumenter, NoDataAttributeDocumenter]: if not issubclass(registry.get(cls.objtype), cls): app.add_autodocumenter(cls, override=True) # group event app.add_event('autodocsumm-grouper') # config value app.add_config_value('autodata_content', 'class', True) app.add_config_value('document_data', True, True) app.add_config_value('not_document_data', [], True) return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
def get_documenter(app, obj, parent): # type: (Sphinx, Any, Any) -> Type[Documenter] """Get an autodoc.Documenter class suitable for documenting the given object. *obj* is the Python object to be documented, and *parent* is an another Python object (e.g. a module or a class) to which *obj* belongs to. """ from sphinx.ext.autodoc import DataDocumenter, ModuleDocumenter if inspect.ismodule(obj): # ModuleDocumenter.can_document_member always returns False return ModuleDocumenter # Construct a fake documenter for *parent* if parent is not None: parent_doc_cls = get_documenter(app, parent, None) else: parent_doc_cls = ModuleDocumenter if hasattr(parent, '__name__'): parent_doc = parent_doc_cls(FakeDirective(), parent.__name__) else: parent_doc = parent_doc_cls(FakeDirective(), "") # Get the corrent documenter class for *obj* classes = [cls for cls in get_documenters(app).values() if cls.can_document_member(obj, '', False, parent_doc)] if classes: classes.sort(key=lambda cls: cls.priority) return classes[-1] else: return DataDocumenter
def setup(app): registry = get_documenters(app) for cls in [CodeReadMethodDocumenter, CodeReadFunctionDocumenter]: if not issubclass(registry.get(cls.objtype), cls): app.add_autodocumenter(cls, override=True) return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
def get_documenter(*args): # type: (Any) -> Type[Documenter] """Get an autodoc.Documenter class suitable for documenting the given object. *obj* is the Python object to be documented, and *parent* is an another Python object (e.g. a module or a class) to which *obj* belongs to. """ from sphinx.ext.autodoc import DataDocumenter, ModuleDocumenter if len(args) == 3: # new style arguments: (app, obj, parent) app, obj, parent = args else: # old style arguments: (obj, parent) app = _app obj, parent = args warnings.warn( 'the interface of get_documenter() has been changed. ' 'Please give application object as first argument.', RemovedInSphinx20Warning, stacklevel=2) if inspect.ismodule(obj): # ModuleDocumenter.can_document_member always returns False return ModuleDocumenter # Construct a fake documenter for *parent* if parent is not None: parent_doc_cls = get_documenter(app, parent, None) else: parent_doc_cls = ModuleDocumenter if hasattr(parent, '__name__'): parent_doc = parent_doc_cls(FakeDirective(), parent.__name__) else: parent_doc = parent_doc_cls(FakeDirective(), "") # Get the corrent documenter class for *obj* classes = [ cls for cls in get_documenters(app).values() if cls.can_document_member(obj, '', False, parent_doc) ] if classes: classes.sort(key=lambda cls: cls.priority) return classes[-1] else: return DataDocumenter
def run(self): # type: () -> List[nodes.Node] reporter = self.state.document.reporter try: source, lineno = reporter.get_source_and_line( self.lineno) # type: ignore except AttributeError: source, lineno = (None, None) logger.debug('[autodoc] %s:%s: input:\n%s', source, lineno, self.block_text) # look up target Documenter objtype = self.name[4:] # strip prefix (auto-). doccls = get_documenters(self.env.app)[objtype] # process the options with the selected documenter's option_spec try: documenter_options = process_documenter_options( doccls, self.config, self.options) except (KeyError, ValueError, TypeError) as exc: # an option is either unknown or has a wrong type logger.error( 'An option to %s is either unknown or has an invalid value: %s' % (self.name, exc), location=(source, lineno)) return [] # generate the output params = DocumenterBridge(self.env, reporter, documenter_options, lineno) documenter = doccls(params, self.arguments[0]) documenter.generate(more_content=self.content) if not params.result: return [] logger.debug('[autodoc] output:\n%s', '\n'.join(params.result)) # record all filenames as dependencies -- this will at least # partially make automatic invalidation possible for fn in params.filename_set: self.state.document.settings.record_dependencies.add(fn) result = parse_generated_content(self.state, params.result, documenter) return result
def get_documenter(*args): # type: (Any) -> Type[Documenter] """Get an autodoc.Documenter class suitable for documenting the given object. *obj* is the Python object to be documented, and *parent* is an another Python object (e.g. a module or a class) to which *obj* belongs to. """ from sphinx.ext.autodoc import DataDocumenter, ModuleDocumenter if len(args) == 3: # new style arguments: (app, obj, parent) app, obj, parent = args else: # old style arguments: (obj, parent) app = _app obj, parent = args warnings.warn('the interface of get_documenter() has been changed. ' 'Please give application object as first argument.', RemovedInSphinx20Warning) if inspect.ismodule(obj): # ModuleDocumenter.can_document_member always returns False return ModuleDocumenter # Construct a fake documenter for *parent* if parent is not None: parent_doc_cls = get_documenter(app, parent, None) else: parent_doc_cls = ModuleDocumenter if hasattr(parent, '__name__'): parent_doc = parent_doc_cls(FakeDirective(), parent.__name__) else: parent_doc = parent_doc_cls(FakeDirective(), "") # Get the corrent documenter class for *obj* classes = [cls for cls in get_documenters(app).values() if cls.can_document_member(obj, '', False, parent_doc)] if classes: classes.sort(key=lambda cls: cls.priority) return classes[-1] else: return DataDocumenter
def run(self): # type: () -> List[nodes.Node] env = self.state.document.settings.env reporter = self.state.document.reporter try: source, lineno = reporter.get_source_and_line(self.lineno) except AttributeError: source, lineno = (None, None) logger.debug('[autodoc] %s:%s: input:\n%s', source, lineno, self.block_text) # look up target Documenter objtype = self.name[4:] # strip prefix (auto-). doccls = get_documenters(env.app)[objtype] # process the options with the selected documenter's option_spec try: documenter_options = process_documenter_options(doccls, env.config, self.options) except (KeyError, ValueError, TypeError) as exc: # an option is either unknown or has a wrong type logger.error('An option to %s is either unknown or has an invalid value: %s' % (self.name, exc), location=(source, lineno)) return [] # generate the output params = DocumenterBridge(env, reporter, documenter_options, lineno) documenter = doccls(params, self.arguments[0]) documenter.generate(more_content=self.content) if not params.result: return [] logger.debug('[autodoc] output:\n%s', '\n'.join(params.result)) # record all filenames as dependencies -- this will at least # partially make automatic invalidation possible for fn in params.filename_set: self.state.document.settings.record_dependencies.add(fn) result = parse_generated_content(self.state, params.result, documenter) return result
def autosummary_documenter(self): """Returns the AutosummaryDocumenter subclass that can be used""" try: return self._autosummary_documenter except AttributeError: pass objtype = self.name[4:] env = self.state.document.settings.env if sphinx_version < [1, 7]: doc_class = self._registry[objtype] params = self else: reporter = self.state.document.reporter try: lineno = reporter.get_source_and_line(self.lineno)[1] except AttributeError: lineno = None doc_class = get_documenters(self.env.app)[objtype] args = (self.state, ) if sphinx_version >= [2, 1] else () params = DocumenterBridge( env, reporter, process_documenter_options(doc_class, env.config, self.options), lineno, *args) documenter = doc_class(params, self.arguments[0]) if hasattr(documenter, 'get_grouped_documenters'): self._autosummary_documenter = documenter return documenter # in case the has been changed in the registry, we decide manually if objtype == 'module': documenter = AutoSummModuleDocumenter(params, self.arguments[0]) elif objtype == 'class': documenter = AutoSummClassDocumenter(params, self.arguments[0]) else: raise ValueError( "Could not find a valid documenter for the object type %s" % ( objtype)) self._autosummary_documenter = documenter return documenter
def get_grouped_documenters(self, all_members=False): """Method to return the member documenters This method is somewhat like a combination of the :meth:`sphinx.ext.autodoc.ModuleDocumenter.generate` method and the :meth:`sphinx.ext.autodoc.ModuleDocumenter.document_members` method. Hence it initializes this instance by importing the object, etc. and it finds the documenters to use for the autosummary option in the same style as the document_members does it. Returns ------- dict dictionary whose keys are determined by the :attr:`member_sections` dictionary and whose values are lists of tuples. Each tuple consists of a documenter and a boolean to identify whether a module check should be made describes an attribute or not. The dictionary can be used in the :meth:`AutoSummDirective.get_items_from_documenters` method Notes ----- If a :class:`sphinx.ext.autodoc.Documenter.member_order` value is not in the :attr:`member_sections` dictionary, it will be put into an additional `Miscellaneous` section.""" self.parse_name() self.import_object() # If there is no real module defined, figure out which to use. # The real module is used in the module analyzer to look up the module # where the attribute documentation would actually be found in. # This is used for situations where you have a module that collects the # functions and classes of internal submodules. self.real_modname = None or self.get_real_modname() # try to also get a source code analyzer for attribute docs try: self.analyzer = ModuleAnalyzer.for_module(self.real_modname) # parse right now, to get PycodeErrors on parsing (results will # be cached anyway) self.analyzer.find_attr_docs() except PycodeError as err: logger.debug('[autodocsumm] module analyzer failed: %s', err) # no source file -- e.g. for builtin and C modules self.analyzer = None # at least add the module.__file__ as a dependency if hasattr(self.module, '__file__') and self.module.__file__: self.directive.filename_set.add(self.module.__file__) else: self.directive.filename_set.add(self.analyzer.srcname) self.env.temp_data['autodoc:module'] = self.modname if self.objpath: self.env.temp_data['autodoc:class'] = self.objpath[0] # set the members from the autosummary member options options_save = {} for option in member_options.intersection(self.option_spec): autopt = 'autosummary-' + option if getattr(self.options, autopt): options_save[option] = getattr(self.options, option) self.options[option] = getattr(self.options, autopt) want_all = all_members or self.options.inherited_members or \ self.options.members is ALL # find out which members are documentable members_check_module, members = self.get_object_members(want_all) # remove members given by exclude-members if self.options.exclude_members: members = [(membername, member) for (membername, member) in members if membername not in self.options.exclude_members] # document non-skipped members memberdocumenters = [] if sphinx_version < [1, 7]: registry = AutodocRegistry._registry else: registry = get_documenters(self.env.app) for (mname, member, isattr) in self.filter_members(members, want_all): classes = [cls for cls in six.itervalues(registry) if cls.can_document_member(member, mname, isattr, self)] if not classes: # don't know how to document this member continue # prefer the documenter with the highest priority classes.sort(key=lambda cls: cls.priority) # give explicitly separated module name, so that members # of inner classes can be documented full_mname = self.modname + '::' + \ '.'.join(self.objpath + [mname]) documenter = classes[-1](self.directive, full_mname, self.indent) memberdocumenters.append((documenter, members_check_module and not isattr)) documenters = OrderedDict() for e in memberdocumenters: section = self.member_sections.get( e[0].member_order, 'Miscellaneous') if self.env.app: e[0].parse_name() e[0].import_object() user_section = self.env.app.emit_firstresult( 'autodocsumm-grouper', self.objtype, e[0].object_name, e[0].object, section, self.object) section = user_section or section documenters.setdefault(section, []).append(e) self.options.update(options_save) return documenters