mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Refactor generate_rst into a class.
This commit is contained in:
@@ -202,309 +202,312 @@ def get_module_charset(module):
|
||||
return charset
|
||||
|
||||
|
||||
def get_doc(what, name, obj, options, env):
|
||||
"""Format and yield lines of the docstring(s) for the object."""
|
||||
docstrings = []
|
||||
if getattr(obj, '__doc__', None):
|
||||
docstrings.append(obj.__doc__)
|
||||
# skip some lines in module docstrings if configured
|
||||
if what == 'module' and env.config.automodule_skip_lines and docstrings:
|
||||
docstrings[0] = '\n'.join(docstrings[0].splitlines()
|
||||
[env.config.automodule_skip_lines:])
|
||||
# for classes, what the "docstring" is can be controlled via an option
|
||||
if what in ('class', 'exception'):
|
||||
content = env.config.autoclass_content
|
||||
if content in ('both', 'init'):
|
||||
initdocstring = getattr(obj, '__init__', None).__doc__
|
||||
# for new-style classes, no __init__ means default __init__
|
||||
if initdocstring == object.__init__.__doc__:
|
||||
initdocstring = None
|
||||
if initdocstring:
|
||||
if content == 'init':
|
||||
docstrings = [initdocstring]
|
||||
class RstGenerator(object):
|
||||
def __init__(self, options, document, lineno):
|
||||
self.options = options
|
||||
self.env = document.settings.env
|
||||
self.reporter = document.reporter
|
||||
self.lineno = lineno
|
||||
self.filename_set = set()
|
||||
self.warnings = []
|
||||
self.result = ViewList()
|
||||
|
||||
def warn(self, msg):
|
||||
self.warnings.append(self.reporter.warning(msg, line=self.lineno))
|
||||
|
||||
def get_doc(self, what, name, obj):
|
||||
"""Format and yield lines of the docstring(s) for the object."""
|
||||
docstrings = []
|
||||
if getattr(obj, '__doc__', None):
|
||||
docstrings.append(obj.__doc__)
|
||||
# skip some lines in module docstrings if configured
|
||||
if what == 'module' and self.env.config.automodule_skip_lines and docstrings:
|
||||
docstrings[0] = '\n'.join(docstrings[0].splitlines()
|
||||
[self.env.config.automodule_skip_lines:])
|
||||
# for classes, what the "docstring" is can be controlled via an option
|
||||
if what in ('class', 'exception'):
|
||||
content = self.env.config.autoclass_content
|
||||
if content in ('both', 'init'):
|
||||
initdocstring = getattr(obj, '__init__', None).__doc__
|
||||
# for new-style classes, no __init__ means default __init__
|
||||
if initdocstring == object.__init__.__doc__:
|
||||
initdocstring = None
|
||||
if initdocstring:
|
||||
if content == 'init':
|
||||
docstrings = [initdocstring]
|
||||
else:
|
||||
docstrings.append('\n\n' + initdocstring)
|
||||
# the default is only the class docstring
|
||||
|
||||
# decode the docstrings using the module's source encoding
|
||||
charset = None
|
||||
module = getattr(obj, '__module__', None)
|
||||
if module is not None:
|
||||
charset = get_module_charset(module)
|
||||
|
||||
for docstring in docstrings:
|
||||
if isinstance(docstring, str):
|
||||
if charset:
|
||||
docstring = docstring.decode(charset)
|
||||
else:
|
||||
docstrings.append('\n\n' + initdocstring)
|
||||
# the default is only the class docstring
|
||||
try:
|
||||
# try decoding with utf-8, should only work for real UTF-8
|
||||
docstring = docstring.decode('utf-8')
|
||||
except UnicodeError:
|
||||
# last resort -- can't fail
|
||||
docstring = docstring.decode('latin1')
|
||||
docstringlines = prepare_docstring(docstring)
|
||||
if self.env.app:
|
||||
# let extensions preprocess docstrings
|
||||
self.env.app.emit('autodoc-process-docstring',
|
||||
what, name, obj, self.options, docstringlines)
|
||||
for line in docstringlines:
|
||||
yield line
|
||||
|
||||
# decode the docstrings using the module's source encoding
|
||||
charset = None
|
||||
module = getattr(obj, '__module__', None)
|
||||
if module is not None:
|
||||
charset = get_module_charset(module)
|
||||
def resolve_name(self, what, name):
|
||||
"""
|
||||
Determine what module to import and what attribute to document.
|
||||
|
||||
for docstring in docstrings:
|
||||
if isinstance(docstring, str):
|
||||
if charset:
|
||||
docstring = docstring.decode(charset)
|
||||
else:
|
||||
try:
|
||||
# try decoding with utf-8, should only work for real UTF-8
|
||||
docstring = docstring.decode('utf-8')
|
||||
except UnicodeError:
|
||||
# last resort -- can't fail
|
||||
docstring = docstring.decode('latin1')
|
||||
docstringlines = prepare_docstring(docstring)
|
||||
if env.app:
|
||||
# let extensions preprocess docstrings
|
||||
env.app.emit('autodoc-process-docstring',
|
||||
what, name, obj, options, docstringlines)
|
||||
for line in docstringlines:
|
||||
yield line
|
||||
|
||||
|
||||
def format_signature(what, obj):
|
||||
"""Return the signature of the object, formatted for display."""
|
||||
if what not in ('class', 'method', 'function'):
|
||||
return ''
|
||||
if what == 'class':
|
||||
# for classes, the relevant signature is the __init__ method's
|
||||
obj = getattr(obj, '__init__', None)
|
||||
# classes without __init__ method?
|
||||
if obj is None or obj is object.__init__ or not \
|
||||
(inspect.ismethod(obj) or inspect.isfunction(obj)):
|
||||
return ''
|
||||
argspec = inspect.getargspec(obj)
|
||||
if what in ('class', 'method') and argspec[0] and \
|
||||
argspec[0][0] in ('cls', 'self'):
|
||||
del argspec[0][0]
|
||||
return inspect.formatargspec(*argspec)
|
||||
|
||||
|
||||
def generate_rst(what, name, members, options, add_content, document, lineno,
|
||||
indent=u'', filename_set=None, check_module=False):
|
||||
env = document.settings.env
|
||||
|
||||
result = None
|
||||
|
||||
# first, parse the definition -- auto directives for classes and functions
|
||||
# can contain a signature which is then used instead of an autogenerated one
|
||||
try:
|
||||
path, base, signature, retann = py_sig_re.match(name).groups()
|
||||
except:
|
||||
warning = document.reporter.warning(
|
||||
'invalid signature for auto%s (%r)' % (what, name), line=lineno)
|
||||
return [warning], result
|
||||
# fullname is the fully qualified name, base the name after the last dot
|
||||
fullname = (path or '') + base
|
||||
# path is the name up to the last dot
|
||||
path = path and path.rstrip('.')
|
||||
|
||||
warnings = []
|
||||
|
||||
# determine what module to import -- mod is the module name, objpath the
|
||||
# path of names to get via getattr
|
||||
mod = None
|
||||
if what == 'module':
|
||||
mod = fullname
|
||||
if signature:
|
||||
warnings.append(document.reporter.warning(
|
||||
'ignoring arguments for automodule %s' % mod, line=lineno))
|
||||
objpath = []
|
||||
elif what in ('class', 'exception', 'function'):
|
||||
if path:
|
||||
mod = path
|
||||
else:
|
||||
# if documenting a toplevel object without explicit module, it can
|
||||
# be contained in another auto directive ...
|
||||
if hasattr(env, 'autodoc_current_module'):
|
||||
mod = env.autodoc_current_module
|
||||
# ... or in the scope of a module directive
|
||||
if not mod:
|
||||
mod = env.currmodule
|
||||
objpath = [base]
|
||||
else:
|
||||
if path:
|
||||
mod_cls = path
|
||||
else:
|
||||
# if documenting a class-level object without path, there must be a
|
||||
# current class, either from a parent auto directive ...
|
||||
if hasattr(env, 'autodoc_current_class'):
|
||||
mod_cls = env.autodoc_current_class
|
||||
# ... or from a class directive
|
||||
if not mod_cls:
|
||||
mod_cls = env.currclass
|
||||
mod, cls = rpartition(mod_cls, '.')
|
||||
# if the module name is still missing, get it like above
|
||||
if not mod and hasattr(env, 'autodoc_current_module'):
|
||||
mod = env.autodoc_current_module
|
||||
if not mod:
|
||||
mod = env.currmodule
|
||||
objpath = [cls, base]
|
||||
|
||||
# by this time, a module *must* be determined
|
||||
if mod is None:
|
||||
warnings.append(document.reporter.warning(
|
||||
'don\'t know which module to import for autodocumenting %r '
|
||||
'(try placing a "module" or "currentmodule" directive in the document, '
|
||||
'or giving an explicit module name)' % fullname, line=lineno))
|
||||
return warnings, result
|
||||
|
||||
# the name to put into the generated directive -- doesn't contain the module
|
||||
name_in_directive = '.'.join(objpath) or mod
|
||||
|
||||
# now, import the module and get docstring(s) of object to document
|
||||
try:
|
||||
todoc = module = __import__(mod, None, None, ['foo'])
|
||||
if hasattr(module, '__file__') and module.__file__:
|
||||
modfile = module.__file__
|
||||
if modfile[-4:].lower() in ('.pyc', '.pyo'):
|
||||
modfile = modfile[:-1]
|
||||
if filename_set is not None:
|
||||
filename_set.add(modfile)
|
||||
else:
|
||||
modfile = None # e.g. for builtin and C modules
|
||||
for part in objpath:
|
||||
todoc = getattr(todoc, part)
|
||||
except (ImportError, AttributeError), err:
|
||||
warnings.append(document.reporter.warning(
|
||||
'autodoc can\'t import/find %s %r, it reported error: "%s",'
|
||||
'please check your spelling and sys.path' %
|
||||
(what, str(fullname), err), line=lineno))
|
||||
return warnings, result
|
||||
|
||||
# check __module__ of object if wanted (for members not given explicitly)
|
||||
if check_module:
|
||||
if hasattr(todoc, '__module__'):
|
||||
if todoc.__module__ != mod:
|
||||
return warnings, result
|
||||
|
||||
# format the object's signature, if any
|
||||
if signature is not None:
|
||||
# signature given explicitly -- the parentheses were stripped by the regex
|
||||
args = '(%s)' % signature
|
||||
if retann:
|
||||
args += retann
|
||||
else:
|
||||
Returns a tuple of: the full name, the module name, a path of
|
||||
names to get via getattr, the signature and return annotation.
|
||||
"""
|
||||
# first, parse the definition -- auto directives for classes and functions
|
||||
# can contain a signature which is then used instead of an autogenerated one
|
||||
try:
|
||||
args = format_signature(what, todoc)
|
||||
except Exception, err:
|
||||
warnings.append(document.reporter.warning(
|
||||
'error while formatting signature for %s: %s' %
|
||||
(fullname, err), line=lineno))
|
||||
args = ''
|
||||
path, base, args, retann = py_sig_re.match(name).groups()
|
||||
except:
|
||||
self.warn('invalid signature for auto%s (%r)' % (what, name))
|
||||
return
|
||||
# fullname is the fully qualified name, base the name after the last dot
|
||||
fullname = (path or '') + base
|
||||
|
||||
# make sure that the view list starts with an empty line. This is
|
||||
# necessary for some situations where another directive preprocesses
|
||||
# reST and no starting newline is present
|
||||
result = ViewList()
|
||||
result.append(u'', '')
|
||||
|
||||
# now, create the directive header
|
||||
directive = (what == 'method' and is_static_method(todoc)) \
|
||||
and 'staticmethod' or what
|
||||
result.append(indent + u'.. %s:: %s%s' % (directive, name_in_directive, args),
|
||||
'<autodoc>')
|
||||
if what == 'module':
|
||||
# Add some module-specific options
|
||||
if options.synopsis:
|
||||
result.append(indent + u' :synopsis: ' + options.synopsis, '<autodoc>')
|
||||
if options.platform:
|
||||
result.append(indent + u' :platform: ' + options.platform, '<autodoc>')
|
||||
if options.deprecated:
|
||||
result.append(indent + u' :deprecated:', '<autodoc>')
|
||||
else:
|
||||
# Be explicit about the module, this is necessary since .. class:: doesn't
|
||||
# support a prepended module name
|
||||
result.append(indent + u' :module: %s' % mod, '<autodoc>')
|
||||
if options.noindex:
|
||||
result.append(indent + u' :noindex:', '<autodoc>')
|
||||
result.append(u'', '<autodoc>')
|
||||
|
||||
if options.show_inheritance and what in ('class', 'exception'):
|
||||
if len(todoc.__bases__):
|
||||
bases = [b.__module__ == '__builtin__' and
|
||||
u':class:`%s`' % b.__name__ or
|
||||
u':class:`%s.%s`' % (b.__module__, b.__name__)
|
||||
for b in todoc.__bases__]
|
||||
result.append(indent + u' Bases: %s' % ', '.join(bases), '<autodoc>')
|
||||
result.append(u'', '<autodoc>')
|
||||
|
||||
# the module directive doesn't have content
|
||||
if what != 'module':
|
||||
indent += u' '
|
||||
|
||||
if modfile:
|
||||
sourcename = '%s:docstring of %s' % (modfile, fullname)
|
||||
else:
|
||||
sourcename = 'docstring of %s' % fullname
|
||||
|
||||
# add content from docstrings
|
||||
for i, line in enumerate(get_doc(what, fullname, todoc, options, env)):
|
||||
result.append(indent + line, sourcename, i)
|
||||
|
||||
# add source content, if present
|
||||
if add_content:
|
||||
for line, src in zip(add_content.data, add_content.items):
|
||||
result.append(indent + line, src[0], src[1])
|
||||
|
||||
# document members?
|
||||
if not members or what in ('function', 'method', 'attribute'):
|
||||
return warnings, result
|
||||
|
||||
# set current namespace for finding members
|
||||
env.autodoc_current_module = mod
|
||||
if objpath:
|
||||
env.autodoc_current_class = objpath[0]
|
||||
|
||||
# add members, if possible
|
||||
_all = members == ['__all__']
|
||||
members_check_module = False
|
||||
if _all:
|
||||
# unqualified :members: given
|
||||
if what == 'module':
|
||||
# for implicit module members, check __module__ to avoid documenting
|
||||
# imported objects if __all__ is not defined
|
||||
members_check_module = not hasattr(todoc, '__all__')
|
||||
all_members = inspect.getmembers(todoc)
|
||||
if args or retann:
|
||||
self.warn('ignoring signature arguments and return annotation '
|
||||
'for automodule %s' % mod)
|
||||
return fullname, fullname, [], None, None
|
||||
|
||||
elif what in ('class', 'exception', 'function'):
|
||||
if path:
|
||||
mod = path.rstrip('.')
|
||||
else:
|
||||
mod = None
|
||||
# if documenting a toplevel object without explicit module, it can
|
||||
# be contained in another auto directive ...
|
||||
if hasattr(self.env, 'autodoc_current_module'):
|
||||
mod = self.env.autodoc_current_module
|
||||
# ... or in the scope of a module directive
|
||||
if not mod:
|
||||
mod = self.env.currmodule
|
||||
return fullname, mod, [base], args, retann
|
||||
|
||||
else:
|
||||
if options.inherited_members:
|
||||
# getmembers() uses dir() which pulls in members from all base classes
|
||||
if path:
|
||||
mod_cls = path.rstrip('.')
|
||||
else:
|
||||
# if documenting a class-level object without path, there must be a
|
||||
# current class, either from a parent auto directive ...
|
||||
if hasattr(self.env, 'autodoc_current_class'):
|
||||
mod_cls = self.env.autodoc_current_class
|
||||
# ... or from a class directive
|
||||
if not mod_cls:
|
||||
mod_cls = self.env.currclass
|
||||
mod, cls = rpartition(mod_cls, '.')
|
||||
# if the module name is still missing, get it like above
|
||||
if not mod and hasattr(self.env, 'autodoc_current_module'):
|
||||
mod = self.env.autodoc_current_module
|
||||
if not mod:
|
||||
mod = self.env.currmodule
|
||||
return fullname, mod, [cls, base], args, retann
|
||||
|
||||
def format_signature(self, what, obj, args, retann):
|
||||
"""
|
||||
Return the signature of the object, formatted for display.
|
||||
"""
|
||||
if what not in ('class', 'method', 'function'):
|
||||
return ''
|
||||
if args is not None:
|
||||
# signature given explicitly
|
||||
return '(%s)%s' % (args, retann or '')
|
||||
if what == 'class':
|
||||
# for classes, the relevant signature is the __init__ method's
|
||||
obj = getattr(obj, '__init__', None)
|
||||
# classes without __init__ method?
|
||||
if obj is None or obj is object.__init__ or not \
|
||||
(inspect.ismethod(obj) or inspect.isfunction(obj)):
|
||||
return ''
|
||||
argspec = inspect.getargspec(obj)
|
||||
if what in ('class', 'method') and argspec[0] and \
|
||||
argspec[0][0] in ('cls', 'self'):
|
||||
del argspec[0][0]
|
||||
return inspect.formatargspec(*argspec)
|
||||
|
||||
def generate(self, what, name, members, add_content, indent=u'', check_module=False):
|
||||
"""
|
||||
Generate reST for the object in self.result.
|
||||
"""
|
||||
fullname, mod, objpath, args, retann = self.resolve_name(what, name)
|
||||
if not mod:
|
||||
# need a module to import
|
||||
self.warn('don\'t know which module to import for autodocumenting %r '
|
||||
'(try placing a "module" or "currentmodule" directive in the '
|
||||
'document, or giving an explicit module name)' % fullname)
|
||||
return
|
||||
|
||||
# the name to put into the generated directive -- doesn't contain the module
|
||||
name_in_directive = '.'.join(objpath) or mod
|
||||
|
||||
# now, import the module and get object to document
|
||||
try:
|
||||
todoc = module = __import__(mod, None, None, ['foo'])
|
||||
if hasattr(module, '__file__') and module.__file__:
|
||||
modfile = module.__file__
|
||||
if modfile[-4:].lower() in ('.pyc', '.pyo'):
|
||||
modfile = modfile[:-1]
|
||||
self.filename_set.add(modfile)
|
||||
else:
|
||||
modfile = None # e.g. for builtin and C modules
|
||||
for part in objpath:
|
||||
todoc = getattr(todoc, part)
|
||||
except (ImportError, AttributeError), err:
|
||||
self.warn('autodoc can\'t import/find %s %r, it reported error: "%s",'
|
||||
'please check your spelling and sys.path' %
|
||||
(what, str(fullname), err))
|
||||
return
|
||||
|
||||
# check __module__ of object if wanted (for members not given explicitly)
|
||||
if check_module:
|
||||
if hasattr(todoc, '__module__'):
|
||||
if todoc.__module__ != mod:
|
||||
return
|
||||
|
||||
# format the object's signature, if any
|
||||
try:
|
||||
sig = self.format_signature(what, todoc, args, retann)
|
||||
except Exception, err:
|
||||
self.warn('error while formatting signature for %s: %s' %
|
||||
(fullname, err))
|
||||
sig = ''
|
||||
|
||||
# make sure that the result starts with an empty line. This is
|
||||
# necessary for some situations where another directive preprocesses
|
||||
# reST and no starting newline is present
|
||||
self.result.append(u'', '')
|
||||
|
||||
# now, create the directive header
|
||||
directive = (what == 'method' and is_static_method(todoc)) \
|
||||
and 'staticmethod' or what
|
||||
self.result.append(indent + u'.. %s:: %s%s' %
|
||||
(directive, name_in_directive, sig), '<autodoc>')
|
||||
if what == 'module':
|
||||
# Add some module-specific options
|
||||
if self.options.synopsis:
|
||||
self.result.append(indent + u' :synopsis: ' + self.options.synopsis,
|
||||
'<autodoc>')
|
||||
if self.options.platform:
|
||||
self.result.append(indent + u' :platform: ' + self.options.platform,
|
||||
'<autodoc>')
|
||||
if self.options.deprecated:
|
||||
self.result.append(indent + u' :deprecated:', '<autodoc>')
|
||||
else:
|
||||
# Be explicit about the module, this is necessary since .. class:: doesn't
|
||||
# support a prepended module name
|
||||
self.result.append(indent + u' :module: %s' % mod, '<autodoc>')
|
||||
if self.options.noindex:
|
||||
self.result.append(indent + u' :noindex:', '<autodoc>')
|
||||
self.result.append(u'', '<autodoc>')
|
||||
|
||||
if self.options.show_inheritance and what in ('class', 'exception'):
|
||||
if len(todoc.__bases__):
|
||||
bases = [b.__module__ == '__builtin__' and
|
||||
u':class:`%s`' % b.__name__ or
|
||||
u':class:`%s.%s`' % (b.__module__, b.__name__)
|
||||
for b in todoc.__bases__]
|
||||
self.result.append(indent + u' Bases: %s' % ', '.join(bases),
|
||||
'<autodoc>')
|
||||
self.result.append(u'', '<autodoc>')
|
||||
|
||||
# the module directive doesn't have content
|
||||
if what != 'module':
|
||||
indent += u' '
|
||||
|
||||
if modfile:
|
||||
sourcename = '%s:docstring of %s' % (modfile, fullname)
|
||||
else:
|
||||
sourcename = 'docstring of %s' % fullname
|
||||
|
||||
# add content from docstrings
|
||||
for i, line in enumerate(self.get_doc(what, fullname, todoc)):
|
||||
self.result.append(indent + line, sourcename, i)
|
||||
|
||||
# add source content, if present
|
||||
if add_content:
|
||||
for line, src in zip(add_content.data, add_content.items):
|
||||
self.result.append(indent + line, src[0], src[1])
|
||||
|
||||
# document members?
|
||||
if not members or what in ('function', 'method', 'attribute'):
|
||||
return
|
||||
|
||||
# set current namespace for finding members
|
||||
self.env.autodoc_current_module = mod
|
||||
if objpath:
|
||||
self.env.autodoc_current_class = objpath[0]
|
||||
|
||||
# add members, if possible
|
||||
_all = members == ['__all__']
|
||||
members_check_module = False
|
||||
if _all:
|
||||
# unqualified :members: given
|
||||
if what == 'module':
|
||||
# for implicit module members, check __module__ to avoid documenting
|
||||
# imported objects if __all__ is not defined
|
||||
members_check_module = not hasattr(todoc, '__all__')
|
||||
all_members = inspect.getmembers(todoc)
|
||||
else:
|
||||
# __dict__ contains only the members directly defined in the class
|
||||
all_members = sorted(todoc.__dict__.iteritems())
|
||||
else:
|
||||
all_members = [(mname, getattr(todoc, mname)) for mname in members]
|
||||
for (membername, member) in all_members:
|
||||
# ignore members whose name starts with _ by default
|
||||
if _all and membername.startswith('_'):
|
||||
continue
|
||||
# ignore undocumented members if :undoc-members: is not given
|
||||
doc = getattr(member, '__doc__', None)
|
||||
if not options.undoc_members and not doc:
|
||||
continue
|
||||
if what == 'module':
|
||||
if isinstance(member, types.FunctionType):
|
||||
memberwhat = 'function'
|
||||
elif isinstance(member, types.ClassType) or \
|
||||
isinstance(member, type):
|
||||
if issubclass(member, base_exception):
|
||||
memberwhat = 'exception'
|
||||
if self.options.inherited_members:
|
||||
# getmembers() uses dir() which pulls in members from all
|
||||
# base classes
|
||||
all_members = inspect.getmembers(todoc)
|
||||
else:
|
||||
memberwhat = 'class'
|
||||
else:
|
||||
# XXX: todo -- attribute docs
|
||||
continue
|
||||
# __dict__ contains only the members directly defined in the class
|
||||
all_members = sorted(todoc.__dict__.iteritems())
|
||||
else:
|
||||
if callable(member):
|
||||
memberwhat = 'method'
|
||||
elif isdescriptor(member):
|
||||
memberwhat = 'attribute'
|
||||
else:
|
||||
# XXX: todo -- attribute docs
|
||||
all_members = [(mname, getattr(todoc, mname)) for mname in members]
|
||||
for (membername, member) in all_members:
|
||||
# ignore members whose name starts with _ by default
|
||||
if _all and membername.startswith('_'):
|
||||
continue
|
||||
full_membername = fullname + '.' + membername
|
||||
subwarn, subres = generate_rst(memberwhat, full_membername, ['__all__'],
|
||||
options, None, document, lineno, indent,
|
||||
check_module=members_check_module)
|
||||
warnings.extend(subwarn)
|
||||
if subres is not None:
|
||||
result.extend(subres)
|
||||
# ignore undocumented members if :undoc-members: is not given
|
||||
doc = getattr(member, '__doc__', None)
|
||||
if not self.options.undoc_members and not doc:
|
||||
continue
|
||||
if what == 'module':
|
||||
if isinstance(member, types.FunctionType):
|
||||
memberwhat = 'function'
|
||||
elif isinstance(member, types.ClassType) or \
|
||||
isinstance(member, type):
|
||||
if issubclass(member, base_exception):
|
||||
memberwhat = 'exception'
|
||||
else:
|
||||
memberwhat = 'class'
|
||||
else:
|
||||
# XXX: todo -- attribute docs
|
||||
continue
|
||||
else:
|
||||
if callable(member):
|
||||
memberwhat = 'method'
|
||||
elif isdescriptor(member):
|
||||
memberwhat = 'attribute'
|
||||
else:
|
||||
# XXX: todo -- attribute docs
|
||||
continue
|
||||
full_membername = fullname + '.' + membername
|
||||
self.generate(memberwhat, full_membername, ['__all__'], None, indent,
|
||||
check_module=members_check_module)
|
||||
|
||||
env.autodoc_current_module = None
|
||||
env.autodoc_current_class = None
|
||||
|
||||
return warnings, result
|
||||
self.env.autodoc_current_module = None
|
||||
self.env.autodoc_current_class = None
|
||||
|
||||
|
||||
def _auto_directive(dirname, arguments, options, content, lineno,
|
||||
@@ -524,20 +527,19 @@ def _auto_directive(dirname, arguments, options, content, lineno,
|
||||
genopt.platform = options.get('platform', '')
|
||||
genopt.deprecated = 'deprecated' in options
|
||||
|
||||
filename_set = set()
|
||||
warnings, result = generate_rst(what, name, members, genopt, content, state.document,
|
||||
lineno, filename_set=filename_set)
|
||||
if result is None:
|
||||
return warnings
|
||||
generator = RstGenerator(genopt, state.document, lineno)
|
||||
generator.generate(what, name, members, content)
|
||||
if not generator.result:
|
||||
return generator.warnings
|
||||
|
||||
# record all filenames as dependencies -- this will at least partially make
|
||||
# automatic invalidation possible
|
||||
for fn in filename_set:
|
||||
for fn in generator.filename_set:
|
||||
state.document.settings.env.note_dependency(fn)
|
||||
|
||||
# use a custom reporter that correctly assigns lines to source and lineno
|
||||
old_reporter = state.memo.reporter
|
||||
state.memo.reporter = AutodocReporter(result, state.memo.reporter)
|
||||
state.memo.reporter = AutodocReporter(generator.result, state.memo.reporter)
|
||||
if dirname == 'automodule':
|
||||
node = nodes.section()
|
||||
# hack around title style bookkeeping
|
||||
@@ -545,14 +547,14 @@ def _auto_directive(dirname, arguments, options, content, lineno,
|
||||
surrounding_section_level = state.memo.section_level
|
||||
state.memo.title_styles = []
|
||||
state.memo.section_level = 0
|
||||
state.nested_parse(result, 0, node, match_titles=1)
|
||||
state.nested_parse(generator.result, 0, node, match_titles=1)
|
||||
state.memo.title_styles = surrounding_title_styles
|
||||
state.memo.section_level = surrounding_section_level
|
||||
else:
|
||||
node = nodes.paragraph()
|
||||
state.nested_parse(result, 0, node)
|
||||
state.nested_parse(generator.result, 0, node)
|
||||
state.memo.reporter = old_reporter
|
||||
return warnings + node.children
|
||||
return generator.warnings + node.children
|
||||
|
||||
def auto_directive(*args, **kwds):
|
||||
return _auto_directive(*args, **kwds)
|
||||
|
||||
Reference in New Issue
Block a user