Ticket #8244: trac_8244-conf-autodoc.2.patch

File trac_8244-conf-autodoc.2.patch, 47.1 KB (added by mpatel, 11 years ago)

Replaces "conf_autodoc" patch.

  • doc/common/conf.py

    # HG changeset patch
    # User J. H. Palmieri <palmieri@math.washington.edu>
    # Date 1266614491 28800
    # Node ID b744a8574e8d0b4adb81f6ede47ed5eff546d796
    # Parent  09df9c9b663c08cbc86317c31854afcbd3eec1a7
    trac #8244: conf, autodoc patches
    
    diff --git a/doc/common/conf.py b/doc/common/conf.py
    a b SAGE_DOC = os.path.join(SAGE_ROOT, 'deve 
    66# is relative to the documentation root, use os.path.abspath to make it
    77# absolute, like shown here.
    88#sys.path.append(os.path.abspath('.'))
     9sys.path.append(os.path.abspath(os.path.join(SAGE_DOC, 'common')))
    910
    1011# General configuration
    1112# ---------------------
    1213
    1314# Add any Sphinx extension module names here, as strings. They can be extensions
    1415# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
    15 extensions = ['sphinx.ext.autodoc']
     16extensions = ['sage_autodoc']
    1617
    1718if 'SAGE_DOC_JSMATH' in os.environ:
    1819    extensions.append('sphinx.ext.jsmath')
    def skip_NestedClass(app, what, name, ob 
    292293    sage.misc.misc.)  Otherwise, abide by Sphinx's decision.
    293294    """
    294295    skip_nested = str(obj).find("sage.misc.misc") != -1 and name.find("MainClass.NestedClass") != -1
    295     return skip or skip_nested
    296        
     296    skip_download_worksheets = name.find("userchild_download_worksheets.zip") != -1
     297    return skip or skip_nested or skip_download_worksheets
     298
    297299def process_dollars(app, what, name, obj, options, docstringlines):
    298300    r"""
    299301    Replace dollar signs with backticks.
    300302    See sage.misc.sagedoc.process_dollars for more information
    301303    """
    302     if len(docstringlines) > 0:
     304    if len(docstringlines) > 0 and name.find("process_dollars") == -1:
    303305        from sage.misc.sagedoc import process_dollars as sagedoc_dollars
    304306        s = sagedoc_dollars("\n".join(docstringlines))
    305307        lines = s.split("\n")
    def process_mathtt(app, what, name, obj, 
    311313    Replace \mathtt{BLAH} with \verb|BLAH| if using jsMath.
    312314    See sage.misc.sagedoc.process_mathtt for more information
    313315    """
    314     if len(docstringlines) > 0 and 'SAGE_DOC_JSMATH' in os.environ:
     316    if (len(docstringlines) > 0 and 'SAGE_DOC_JSMATH' in os.environ
     317        and name.find("process_mathtt") == -1):
    315318        from sage.misc.sagedoc import process_mathtt as sagedoc_mathtt
    316319        s = sagedoc_mathtt("\n".join(docstringlines), True)
    317320        lines = s.split("\n")
  • new file doc/common/sage_autodoc.py

    diff --git a/doc/common/sage_autodoc.py b/doc/common/sage_autodoc.py
    new file mode 100644
    - +  
     1# -*- coding: utf-8 -*-
     2"""
     3    sage_autodoc
     4    ~~~~~~~~~~~~
     5
     6    Derived from sphinx.ext.autodoc:
     7
     8    Automatically insert docstrings for functions, classes or whole modules into
     9    the doctree, thus avoiding duplication between docstrings and documentation
     10    for those who like elaborate docstrings.
     11
     12    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
     13    :license: BSD, see LICENSE for details.
     14"""
     15
     16import re
     17import sys
     18import inspect
     19from types import FunctionType, BuiltinFunctionType, MethodType, ClassType
     20
     21from docutils import nodes
     22from docutils.utils import assemble_option_dict
     23from docutils.statemachine import ViewList
     24
     25from sphinx.util import rpartition, nested_parse_with_titles, force_decode
     26from sphinx.pycode import ModuleAnalyzer, PycodeError
     27from sphinx.application import ExtensionError
     28from sphinx.util.compat import Directive
     29from sphinx.util.inspect import isdescriptor, safe_getmembers, safe_getattr
     30from sphinx.util.docstrings import prepare_docstring
     31
     32
     33try:
     34    base_exception = BaseException
     35except NameError:
     36    base_exception = Exception
     37
     38
     39#: extended signature RE: with explicit module name separated by ::
     40py_ext_sig_re = re.compile(
     41    r'''^ ([\w.]+::)?            # explicit module name
     42          ([\w.]+\.)?            # module and/or class name(s)
     43          (\w+)  \s*             # thing name
     44          (?: \((.*)\)           # optional: arguments
     45           (?:\s* -> \s* (.*))?  #           return annotation
     46          )? $                   # and nothing more
     47          ''', re.VERBOSE)
     48
     49
     50class DefDict(dict):
     51    """A dict that returns a default on nonexisting keys."""
     52    def __init__(self, default):
     53        dict.__init__(self)
     54        self.default = default
     55    def __getitem__(self, key):
     56        try:
     57            return dict.__getitem__(self, key)
     58        except KeyError:
     59            return self.default
     60    def __nonzero__(self):
     61        # docutils check "if option_spec"
     62        return True
     63
     64identity = lambda x: x
     65
     66
     67class Options(dict):
     68    """A dict/attribute hybrid that returns None on nonexisting keys."""
     69    def __getattr__(self, name):
     70        try:
     71            return self[name.replace('_', '-')]
     72        except KeyError:
     73            return None
     74
     75
     76ALL = object()
     77
     78def members_option(arg):
     79    """Used to convert the :members: option to auto directives."""
     80    if arg is None:
     81        return ALL
     82    return [x.strip() for x in arg.split(',')]
     83
     84def members_set_option(arg):
     85    """Used to convert the :members: option to auto directives."""
     86    if arg is None:
     87        return ALL
     88    return set(x.strip() for x in arg.split(','))
     89
     90def bool_option(arg):
     91    """Used to convert flag options to auto directives.  (Instead of
     92    directives.flag(), which returns None.)"""
     93    return True
     94
     95
     96class AutodocReporter(object):
     97    """
     98    A reporter replacement that assigns the correct source name
     99    and line number to a system message, as recorded in a ViewList.
     100    """
     101    def __init__(self, viewlist, reporter):
     102        self.viewlist = viewlist
     103        self.reporter = reporter
     104
     105    def __getattr__(self, name):
     106        return getattr(self.reporter, name)
     107
     108    def system_message(self, level, message, *children, **kwargs):
     109        if 'line' in kwargs:
     110            try:
     111                source, line = self.viewlist.items[kwargs['line']]
     112            except IndexError:
     113                pass
     114            else:
     115                kwargs['source'] = source
     116                kwargs['line'] = line
     117        return self.reporter.system_message(level, message,
     118                                            *children, **kwargs)
     119
     120    def debug(self, *args, **kwargs):
     121        if self.reporter.debug_flag:
     122            return self.system_message(0, *args, **kwargs)
     123
     124    def info(self, *args, **kwargs):
     125        return self.system_message(1, *args, **kwargs)
     126
     127    def warning(self, *args, **kwargs):
     128        return self.system_message(2, *args, **kwargs)
     129
     130    def error(self, *args, **kwargs):
     131        return self.system_message(3, *args, **kwargs)
     132
     133    def severe(self, *args, **kwargs):
     134        return self.system_message(4, *args, **kwargs)
     135
     136
     137# Some useful event listener factories for autodoc-process-docstring.
     138
     139def cut_lines(pre, post=0, what=None):
     140    """
     141    Return a listener that removes the first *pre* and last *post*
     142    lines of every docstring.  If *what* is a sequence of strings,
     143    only docstrings of a type in *what* will be processed.
     144
     145    Use like this (e.g. in the ``setup()`` function of :file:`conf.py`)::
     146
     147       from sphinx.ext.autodoc import cut_lines
     148       app.connect('autodoc-process-docstring', cut_lines(4, what=['module']))
     149
     150    This can (and should) be used in place of :confval:`automodule_skip_lines`.
     151    """
     152    def process(app, what_, name, obj, options, lines):
     153        if what and what_ not in what:
     154            return
     155        del lines[:pre]
     156        if post:
     157            # remove one trailing blank line.
     158            if lines and not lines[-1]:
     159                lines.pop(-1)
     160            del lines[-post:]
     161        # make sure there is a blank line at the end
     162        if lines and lines[-1]:
     163            lines.append('')
     164    return process
     165
     166def between(marker, what=None, keepempty=False):
     167    """
     168    Return a listener that only keeps lines between lines that match the
     169    *marker* regular expression.  If no line matches, the resulting docstring
     170    would be empty, so no change will be made unless *keepempty* is true.
     171
     172    If *what* is a sequence of strings, only docstrings of a type in *what* will
     173    be processed.
     174    """
     175    marker_re = re.compile(marker)
     176    def process(app, what_, name, obj, options, lines):
     177        if what and what_ not in what:
     178            return
     179        deleted = 0
     180        delete = True
     181        orig_lines = lines[:]
     182        for i, line in enumerate(orig_lines):
     183            if delete:
     184                lines.pop(i - deleted)
     185                deleted += 1
     186            if marker_re.match(line):
     187                delete = not delete
     188                if delete:
     189                    lines.pop(i - deleted)
     190                    deleted += 1
     191        if not lines and not keepempty:
     192            lines[:] = orig_lines
     193        # make sure there is a blank line at the end
     194        if lines and lines[-1]:
     195            lines.append('')
     196    return process
     197
     198
     199class Documenter(object):
     200    """
     201    A Documenter knows how to autodocument a single object type.  When
     202    registered with the AutoDirective, it will be used to document objects
     203    of that type when needed by autodoc.
     204
     205    Its *objtype* attribute selects what auto directive it is assigned to
     206    (the directive name is 'auto' + objtype), and what directive it generates
     207    by default, though that can be overridden by an attribute called
     208    *directivetype*.
     209
     210    A Documenter has an *option_spec* that works like a docutils directive's;
     211    in fact, it will be used to parse an auto directive's options that matches
     212    the documenter.
     213    """
     214    #: name by which the directive is called (auto...) and the default
     215    #: generated directive name
     216    objtype = 'object'
     217    #: indentation by which to indent the directive content
     218    content_indent = u'   '
     219    #: priority if multiple documenters return True from can_document_member
     220    priority = 0
     221    #: order if autodoc_member_order is set to 'groupwise'
     222    member_order = 0
     223
     224    option_spec = {'noindex': bool_option}
     225
     226    @staticmethod
     227    def get_attr(obj, name, *defargs):
     228        """getattr() override for types such as Zope interfaces."""
     229        for typ, func in AutoDirective._special_attrgetters.iteritems():
     230            if isinstance(obj, typ):
     231                return func(obj, name, *defargs)
     232        return safe_getattr(obj, name, *defargs)
     233
     234    @classmethod
     235    def can_document_member(cls, member, membername, isattr, parent):
     236        """Called to see if a member can be documented by this documenter."""
     237        raise NotImplementedError('must be implemented in subclasses')
     238
     239    def __init__(self, directive, name, indent=u''):
     240        self.directive = directive
     241        self.env = directive.env
     242        self.options = directive.genopt
     243        self.name = name
     244        self.indent = indent
     245        # the module and object path within the module, and the fully
     246        # qualified name (all set after resolve_name succeeds)
     247        self.modname = None
     248        self.module = None
     249        self.objpath = None
     250        self.fullname = None
     251        # extra signature items (arguments and return annotation,
     252        # also set after resolve_name succeeds)
     253        self.args = None
     254        self.retann = None
     255        # the object to document (set after import_object succeeds)
     256        self.object = None
     257        # the module analyzer to get at attribute docs, or None
     258        self.analyzer = None
     259
     260    def add_line(self, line, source, *lineno):
     261        """Append one line of generated reST to the output."""
     262        self.directive.result.append(self.indent + line, source, *lineno)
     263
     264    def resolve_name(self, modname, parents, path, base):
     265        """
     266        Resolve the module and name of the object to document given by the
     267        arguments and the current module/class.
     268
     269        Must return a pair of the module name and a chain of attributes; for
     270        example, it would return ``('zipfile', ['ZipFile', 'open'])`` for the
     271        ``zipfile.ZipFile.open`` method.
     272        """
     273        raise NotImplementedError('must be implemented in subclasses')
     274
     275    def parse_name(self):
     276        """
     277        Determine what module to import and what attribute to document.
     278
     279        Returns True and sets *self.modname*, *self.objpath*, *self.fullname*,
     280        *self.args* and *self.retann* if parsing and resolving was successful.
     281        """
     282        # first, parse the definition -- auto directives for classes and
     283        # functions can contain a signature which is then used instead of
     284        # an autogenerated one
     285        try:
     286            explicit_modname, path, base, args, retann = \
     287                 py_ext_sig_re.match(self.name).groups()
     288        except AttributeError:
     289            self.directive.warn('invalid signature for auto%s (%r)' %
     290                                (self.objtype, self.name))
     291            return False
     292
     293        # support explicit module and class name separation via ::
     294        if explicit_modname is not None:
     295            modname = explicit_modname[:-2]
     296            parents = path and path.rstrip('.').split('.') or []
     297        else:
     298            modname = None
     299            parents = []
     300
     301        self.modname, self.objpath = \
     302                      self.resolve_name(modname, parents, path, base)
     303
     304        if not self.modname:
     305            return False
     306
     307        self.args = args
     308        self.retann = retann
     309        self.fullname = (self.modname or '') + \
     310                        (self.objpath and '.' + '.'.join(self.objpath) or '')
     311        return True
     312
     313    def import_object(self):
     314        """
     315        Import the object given by *self.modname* and *self.objpath* and sets
     316        it as *self.object*.
     317
     318        Returns True if successful, False if an error occurred.
     319        """
     320        try:
     321            __import__(self.modname)
     322            obj = self.module = sys.modules[self.modname]
     323            for part in self.objpath:
     324                obj = self.get_attr(obj, part)
     325            self.object = obj
     326            return True
     327        except (SyntaxError, ImportError, AttributeError), err:
     328            self.directive.warn(
     329                'autodoc can\'t import/find %s %r, it reported error: '
     330                '"%s", please check your spelling and sys.path' %
     331                (self.objtype, str(self.fullname), err))
     332            return False
     333
     334    def get_real_modname(self):
     335        """
     336        Get the real module name of an object to document.  (It can differ
     337        from the name of the module through which the object was imported.)
     338        """
     339        return self.get_attr(self.object, '__module__', None) or self.modname
     340
     341    def check_module(self):
     342        """
     343        Check if *self.object* is really defined in the module given by
     344        *self.modname*.
     345        """
     346        modname = self.get_attr(self.object, '__module__', None)
     347        if modname and modname != self.modname:
     348            return False
     349        return True
     350
     351    def format_args(self):
     352        """
     353        Format the argument signature of *self.object*.  Should return None if
     354        the object does not have a signature.
     355        """
     356        return None
     357
     358    def format_signature(self):
     359        """
     360        Format the signature (arguments and return annotation) of the object.
     361        Let the user process it via the ``autodoc-process-signature`` event.
     362        """
     363        if self.args is not None:
     364            # signature given explicitly
     365            args = "(%s)" % self.args
     366        else:
     367            # try to introspect the signature
     368            args = self.format_args()
     369        if args is None:
     370            return ''
     371        retann = self.retann
     372
     373        result = self.env.app.emit_firstresult(
     374            'autodoc-process-signature', self.objtype, self.fullname,
     375            self.object, self.options, args, retann)
     376        if result:
     377            args, retann = result
     378
     379        if args is not None:
     380            return args + (retann and (' -> %s' % retann) or '')
     381        else:
     382            return ''
     383
     384    def add_directive_header(self, sig):
     385        """Add the directive header and options to the generated content."""
     386        directive = getattr(self, 'directivetype', self.objtype)
     387        # the name to put into the generated directive -- doesn't contain
     388        # the module (except for module directive of course)
     389        name_in_directive = '.'.join(self.objpath) or self.modname
     390        self.add_line(u'.. %s:: %s%s' % (directive, name_in_directive, sig),
     391                      '<autodoc>')
     392        if self.options.noindex:
     393            self.add_line(u'   :noindex:', '<autodoc>')
     394        if self.objpath:
     395            # Be explicit about the module, this is necessary since .. class::
     396            # etc. don't support a prepended module name
     397            self.add_line(u'   :module: %s' % self.modname, '<autodoc>')
     398
     399    def get_doc(self, encoding=None):
     400        """Decode and return lines of the docstring(s) for the object."""
     401        docstring = self.get_attr(self.object, '__doc__', None)
     402        if docstring:
     403            # make sure we have Unicode docstrings, then sanitize and split
     404            # into lines
     405            return [prepare_docstring(force_decode(docstring, encoding))]
     406        return []
     407
     408    def process_doc(self, docstrings):
     409        """Let the user process the docstrings before adding them."""
     410        for docstringlines in docstrings:
     411            if self.env.app:
     412                # let extensions preprocess docstrings
     413                self.env.app.emit('autodoc-process-docstring',
     414                                  self.objtype, self.fullname, self.object,
     415                                  self.options, docstringlines)
     416            for line in docstringlines:
     417                yield line
     418
     419    def add_content(self, more_content, no_docstring=False):
     420        """Add content from docstrings, attribute documentation and user."""
     421        # set sourcename and add content from attribute documentation
     422        if self.analyzer:
     423            # prevent encoding errors when the file name is non-ASCII
     424            filename = unicode(self.analyzer.srcname,
     425                               sys.getfilesystemencoding(), 'replace')
     426            sourcename = u'%s:docstring of %s' % (filename, self.fullname)
     427
     428            attr_docs = self.analyzer.find_attr_docs()
     429            if self.objpath:
     430                key = ('.'.join(self.objpath[:-1]), self.objpath[-1])
     431                if key in attr_docs:
     432                    no_docstring = True
     433                    docstrings = [attr_docs[key]]
     434                    for i, line in enumerate(self.process_doc(docstrings)):
     435                        self.add_line(line, sourcename, i)
     436        else:
     437            sourcename = u'docstring of %s' % self.fullname
     438
     439        # add content from docstrings
     440        if not no_docstring:
     441            encoding = self.analyzer and self.analyzer.encoding
     442            docstrings = self.get_doc(encoding)
     443            for i, line in enumerate(self.process_doc(docstrings)):
     444                self.add_line(line, sourcename, i)
     445
     446        # add additional content (e.g. from document), if present
     447        if more_content:
     448            for line, src in zip(more_content.data, more_content.items):
     449                self.add_line(line, src[0], src[1])
     450
     451    def get_object_members(self, want_all):
     452        """
     453        Return `(members_check_module, members)` where `members` is a
     454        list of `(membername, member)` pairs of the members of *self.object*.
     455
     456        If *want_all* is True, return all members.  Else, only return those
     457        members given by *self.options.members* (which may also be none).
     458        """
     459        if not want_all:
     460            if not self.options.members:
     461                return False, []
     462            # specific members given
     463            ret = []
     464            for mname in self.options.members:
     465                try:
     466                    ret.append((mname, self.get_attr(self.object, mname)))
     467                except AttributeError:
     468                    self.directive.warn('missing attribute %s in object %s'
     469                                        % (mname, self.fullname))
     470            return False, ret
     471        elif self.options.inherited_members:
     472            # safe_getmembers() uses dir() which pulls in members from all
     473            # base classes
     474            return False, safe_getmembers(self.object)
     475        else:
     476            # __dict__ contains only the members directly defined in
     477            # the class (but get them via getattr anyway, to e.g. get
     478            # unbound method objects instead of function objects);
     479            # using keys() because apparently there are objects for which
     480            # __dict__ changes while getting attributes
     481            return False, sorted([
     482                (mname, self.get_attr(self.object, mname, None))
     483                for mname in self.get_attr(self.object, '__dict__').keys()])
     484
     485    def filter_members(self, members, want_all):
     486        """
     487        Filter the given member list: members are skipped if
     488
     489        - they are private (except if given explicitly)
     490        - they are undocumented (except if undoc-members is given)
     491
     492        The user can override the skipping decision by connecting to the
     493        ``autodoc-skip-member`` event.
     494        """
     495        ret = []
     496
     497        # search for members in source code too
     498        namespace = '.'.join(self.objpath)  # will be empty for modules
     499
     500        if self.analyzer:
     501            attr_docs = self.analyzer.find_attr_docs()
     502        else:
     503            attr_docs = {}
     504
     505        # process members and determine which to skip
     506        for (membername, member) in members:
     507            # if isattr is True, the member is documented as an attribute
     508            isattr = False
     509
     510            if want_all and membername.startswith('_'):
     511                # ignore members whose name starts with _ by default
     512                skip = True
     513            elif (namespace, membername) in attr_docs:
     514                # keep documented attributes
     515                skip = False
     516                isattr = True
     517            else:
     518                # ignore undocumented members if :undoc-members:
     519                # is not given
     520                doc = self.get_attr(member, '__doc__', None)
     521                skip = not self.options.undoc_members and not doc
     522
     523            # give the user a chance to decide whether this member
     524            # should be skipped
     525            if self.env.app:
     526                # let extensions preprocess docstrings
     527                skip_user = self.env.app.emit_firstresult(
     528                    'autodoc-skip-member', self.objtype, membername, member,
     529                    skip, self.options)
     530                if skip_user is not None:
     531                    skip = skip_user
     532            if skip:
     533                continue
     534
     535            ret.append((membername, member, isattr))
     536
     537        return ret
     538
     539    def document_members(self, all_members=False):
     540        """
     541        Generate reST for member documentation.  If *all_members* is True,
     542        do all members, else those given by *self.options.members*.
     543        """
     544        # set current namespace for finding members
     545        self.env.autodoc_current_module = self.modname
     546        if self.objpath:
     547            self.env.autodoc_current_class = self.objpath[0]
     548
     549        want_all = all_members or self.options.inherited_members or \
     550                   self.options.members is ALL
     551        # find out which members are documentable
     552        members_check_module, members = self.get_object_members(want_all)
     553
     554        # remove members given by exclude-members
     555        if self.options.exclude_members:
     556            members = [(membername, member) for (membername, member) in members
     557                       if membername not in self.options.exclude_members]
     558
     559        # document non-skipped members
     560        memberdocumenters = []
     561        for (mname, member, isattr) in self.filter_members(members, want_all):
     562            classes = [cls for cls in AutoDirective._registry.itervalues()
     563                       if cls.can_document_member(member, mname, isattr, self)]
     564            if not classes:
     565                # don't know how to document this member
     566                continue
     567            # prefer the documenter with the highest priority
     568            classes.sort(key=lambda cls: cls.priority)
     569            # give explicitly separated module name, so that members
     570            # of inner classes can be documented
     571            full_mname = self.modname + '::' + \
     572                              '.'.join(self.objpath + [mname])
     573            memberdocumenters.append(
     574                classes[-1](self.directive, full_mname, self.indent))
     575
     576        if (self.options.member_order or self.env.config.autodoc_member_order) \
     577               == 'groupwise':
     578            # sort by group; relies on stable sort to keep items in the
     579            # same group sorted alphabetically
     580            memberdocumenters.sort(key=lambda d: d.member_order)
     581
     582        for documenter in memberdocumenters:
     583            documenter.generate(all_members=True,
     584                                real_modname=self.real_modname,
     585                                check_module=members_check_module)
     586
     587        # reset current objects
     588        self.env.autodoc_current_module = None
     589        self.env.autodoc_current_class = None
     590
     591    def generate(self, more_content=None, real_modname=None,
     592                 check_module=False, all_members=False):
     593        """
     594        Generate reST for the object given by *self.name*, and possibly members.
     595
     596        If *more_content* is given, include that content. If *real_modname* is
     597        given, use that module name to find attribute docs. If *check_module* is
     598        True, only generate if the object is defined in the module name it is
     599        imported from. If *all_members* is True, document all members.
     600        """
     601        if not self.parse_name():
     602            # need a module to import
     603            self.directive.warn(
     604                'don\'t know which module to import for autodocumenting '
     605                '%r (try placing a "module" or "currentmodule" directive '
     606                'in the document, or giving an explicit module name)'
     607                % self.name)
     608            return
     609
     610        # now, import the module and get object to document
     611        if not self.import_object():
     612            return
     613
     614        # If there is no real module defined, figure out which to use.
     615        # The real module is used in the module analyzer to look up the module
     616        # where the attribute documentation would actually be found in.
     617        # This is used for situations where you have a module that collects the
     618        # functions and classes of internal submodules.
     619        self.real_modname = real_modname or self.get_real_modname()
     620
     621        # try to also get a source code analyzer for attribute docs
     622        try:
     623            self.analyzer = ModuleAnalyzer.for_module(self.real_modname)
     624            # parse right now, to get PycodeErrors on parsing (results will
     625            # be cached anyway)
     626            self.analyzer.find_attr_docs()
     627        except PycodeError, err:
     628            # no source file -- e.g. for builtin and C modules
     629            self.analyzer = None
     630            # at least add the module.__file__ as a dependency
     631            if hasattr(self.module, '__file__') and self.module.__file__:
     632                self.directive.filename_set.add(self.module.__file__)
     633        else:
     634            self.directive.filename_set.add(self.analyzer.srcname)
     635
     636        # check __module__ of object (for members not given explicitly)
     637        if check_module:
     638            if not self.check_module():
     639                return
     640
     641        # make sure that the result starts with an empty line.  This is
     642        # necessary for some situations where another directive preprocesses
     643        # reST and no starting newline is present
     644        self.add_line(u'', '')
     645
     646        # format the object's signature, if any
     647        try:
     648            sig = self.format_signature()
     649        except Exception, err:
     650            self.directive.warn('error while formatting signature for '
     651                                '%s: %s' % (self.fullname, err))
     652            sig = ''
     653
     654        # generate the directive header and options, if applicable
     655        self.add_directive_header(sig)
     656        self.add_line(u'', '<autodoc>')
     657
     658        # e.g. the module directive doesn't have content
     659        self.indent += self.content_indent
     660
     661        # add all content (from docstrings, attribute docs etc.)
     662        self.add_content(more_content)
     663
     664        # document members, if possible
     665        self.document_members(all_members)
     666
     667
     668class ModuleDocumenter(Documenter):
     669    """
     670    Specialized Documenter subclass for modules.
     671    """
     672    objtype = 'module'
     673    content_indent = u''
     674
     675    option_spec = {
     676        'members': members_option, 'undoc-members': bool_option,
     677        'noindex': bool_option, 'inherited-members': bool_option,
     678        'show-inheritance': bool_option, 'synopsis': identity,
     679        'platform': identity, 'deprecated': bool_option,
     680        'member-order': identity, 'exclude-members': members_set_option,
     681    }
     682
     683    @classmethod
     684    def can_document_member(cls, member, membername, isattr, parent):
     685        # don't document submodules automatically
     686        return False
     687
     688    def resolve_name(self, modname, parents, path, base):
     689        if modname is not None:
     690            self.directive.warn('"::" in automodule name doesn\'t make sense')
     691        return (path or '') + base, []
     692
     693    def parse_name(self):
     694        ret = Documenter.parse_name(self)
     695        if self.args or self.retann:
     696            self.directive.warn('signature arguments or return annotation '
     697                                'given for automodule %s' % self.fullname)
     698        return ret
     699
     700    def add_directive_header(self, sig):
     701        Documenter.add_directive_header(self, sig)
     702
     703        # add some module-specific options
     704        if self.options.synopsis:
     705            self.add_line(
     706                u'   :synopsis: ' + self.options.synopsis, '<autodoc>')
     707        if self.options.platform:
     708            self.add_line(
     709                u'   :platform: ' + self.options.platform, '<autodoc>')
     710        if self.options.deprecated:
     711            self.add_line(u'   :deprecated:', '<autodoc>')
     712
     713    def get_object_members(self, want_all):
     714        if want_all:
     715            if not hasattr(self.object, '__all__'):
     716                # for implicit module members, check __module__ to avoid
     717                # documenting imported objects
     718                return True, safe_getmembers(self.object)
     719            else:
     720                memberlist = self.object.__all__
     721        else:
     722            memberlist = self.options.members or []
     723        ret = []
     724        for mname in memberlist:
     725            try:
     726                ret.append((mname, safe_getattr(self.object, mname)))
     727            except AttributeError:
     728                self.directive.warn(
     729                    'missing attribute mentioned in :members: or __all__: '
     730                    'module %s, attribute %s' % (
     731                    safe_getattr(self.object, '__name__', '???'), mname))
     732        return False, ret
     733
     734
     735class ModuleLevelDocumenter(Documenter):
     736    """
     737    Specialized Documenter subclass for objects on module level (functions,
     738    classes, data/constants).
     739    """
     740    def resolve_name(self, modname, parents, path, base):
     741        if modname is None:
     742            if path:
     743                modname = path.rstrip('.')
     744            else:
     745                # if documenting a toplevel object without explicit module,
     746                # it can be contained in another auto directive ...
     747                if hasattr(self.env, 'autodoc_current_module'):
     748                    modname = self.env.autodoc_current_module
     749                # ... or in the scope of a module directive
     750                if not modname:
     751                    modname = self.env.currmodule
     752                # ... else, it stays None, which means invalid
     753        return modname, parents + [base]
     754
     755
     756class ClassLevelDocumenter(Documenter):
     757    """
     758    Specialized Documenter subclass for objects on class level (methods,
     759    attributes).
     760    """
     761    def resolve_name(self, modname, parents, path, base):
     762        if modname is None:
     763            if path:
     764                mod_cls = path.rstrip('.')
     765            else:
     766                mod_cls = None
     767                # if documenting a class-level object without path,
     768                # there must be a current class, either from a parent
     769                # auto directive ...
     770                if hasattr(self.env, 'autodoc_current_class'):
     771                    mod_cls = self.env.autodoc_current_class
     772                # ... or from a class directive
     773                if mod_cls is None:
     774                    mod_cls = self.env.currclass
     775                # ... if still None, there's no way to know
     776                if mod_cls is None:
     777                    return None, []
     778            modname, cls = rpartition(mod_cls, '.')
     779            parents = [cls]
     780            # if the module name is still missing, get it like above
     781            if not modname and hasattr(self.env, 'autodoc_current_module'):
     782                modname = self.env.autodoc_current_module
     783            if not modname:
     784                modname = self.env.currmodule
     785            # ... else, it stays None, which means invalid
     786        return modname, parents + [base]
     787
     788
     789class FunctionDocumenter(ModuleLevelDocumenter):
     790    """
     791    Specialized Documenter subclass for functions.
     792    """
     793    objtype = 'function'
     794    member_order = 30
     795
     796    @classmethod
     797    def can_document_member(cls, member, membername, isattr, parent):
     798        return isinstance(member, (FunctionType, BuiltinFunctionType))
     799
     800    def format_args(self):
     801        if inspect.isbuiltin(self.object) or \
     802               inspect.ismethoddescriptor(self.object):
     803            # can never get arguments of a C function or method unless
     804            # a function to do so is supplied
     805            if self.env.config.autodoc_builtin_argspec:
     806                argspec = self.env.config.autodoc_builtin_argspec(self.object)
     807                return inspect.formatargspec(*argspec)
     808            else:
     809                return None
     810        try:
     811            argspec = inspect.getargspec(self.object)
     812        except TypeError:
     813            # if a class should be documented as function (yay duck
     814            # typing) we try to use the constructor signature as function
     815            # signature without the first argument.
     816            try:
     817                argspec = inspect.getargspec(self.object.__new__)
     818            except TypeError:
     819                argspec = inspect.getargspec(self.object.__init__)
     820                if argspec[0]:
     821                    del argspec[0][0]
     822        return inspect.formatargspec(*argspec)
     823
     824    def document_members(self, all_members=False):
     825        pass
     826
     827
     828class ClassDocumenter(ModuleLevelDocumenter):
     829    """
     830    Specialized Documenter subclass for classes.
     831    """
     832    objtype = 'class'
     833    member_order = 20
     834    option_spec = {
     835        'members': members_option, 'undoc-members': bool_option,
     836        'noindex': bool_option, 'inherited-members': bool_option,
     837        'show-inheritance': bool_option, 'member-order': identity,
     838        'exclude-members': members_set_option,
     839    }
     840
     841    @classmethod
     842    def can_document_member(cls, member, membername, isattr, parent):
     843        return isinstance(member, (type, ClassType))
     844
     845    def import_object(self):
     846        ret = ModuleLevelDocumenter.import_object(self)
     847        # if the class is documented under another name, document it
     848        # as data/attribute
     849        if ret:
     850            if hasattr(self.object, '__name__'):
     851                self.doc_as_attr = (self.objpath[-1] != self.object.__name__)
     852            else:
     853                self.doc_as_attr = True
     854        return ret
     855
     856    def format_args(self):
     857        args = None
     858        # for classes, the relevant signature is the __init__ method's
     859        initmeth = self.get_attr(self.object, '__init__', None)
     860        # classes without __init__ method, default __init__ or
     861        # __init__ written in C?
     862        if initmeth is None or initmeth is object.__init__ or not \
     863               (inspect.ismethod(initmeth) or inspect.isfunction(initmeth)):
     864            return None
     865        try:
     866            argspec = inspect.getargspec(initmeth)
     867        except TypeError:
     868            # still not possible: happens e.g. for old-style classes
     869            # with __init__ in C
     870            return None
     871        if argspec[0] and argspec[0][0] in ('cls', 'self'):
     872            del argspec[0][0]
     873        return inspect.formatargspec(*argspec)
     874
     875    def format_signature(self):
     876        if self.doc_as_attr:
     877            return ''
     878        return ModuleLevelDocumenter.format_signature(self)
     879
     880    def add_directive_header(self, sig):
     881        if self.doc_as_attr:
     882            self.directivetype = 'attribute'
     883        Documenter.add_directive_header(self, sig)
     884
     885        # add inheritance info, if wanted
     886        if not self.doc_as_attr and self.options.show_inheritance:
     887            self.add_line(u'', '<autodoc>')
     888            if len(self.object.__bases__):
     889                bases = [b.__module__ == '__builtin__' and
     890                         u':class:`%s`' % b.__name__ or
     891                         u':class:`%s.%s`' % (b.__module__, b.__name__)
     892                         for b in self.object.__bases__]
     893                self.add_line(_(u'   Bases: %s') % ', '.join(bases),
     894                              '<autodoc>')
     895
     896    def get_doc(self, encoding=None):
     897        content = self.env.config.autoclass_content
     898
     899        docstrings = []
     900        docstring = self.get_attr(self.object, '__doc__', None)
     901        if docstring:
     902            docstrings.append(docstring)
     903
     904        # for classes, what the "docstring" is can be controlled via a
     905        # config value; the default is only the class docstring
     906        if content in ('both', 'init'):
     907            initdocstring = self.get_attr(
     908                self.get_attr(self.object, '__init__', None), '__doc__')
     909            # for new-style classes, no __init__ means default __init__
     910            if initdocstring == object.__init__.__doc__:
     911                initdocstring = None
     912            if initdocstring:
     913                if content == 'init':
     914                    docstrings = [initdocstring]
     915                else:
     916                    docstrings.append(initdocstring)
     917
     918        return [prepare_docstring(force_decode(docstring, encoding))
     919                for docstring in docstrings]
     920
     921    def add_content(self, more_content, no_docstring=False):
     922        if self.doc_as_attr:
     923            classname = safe_getattr(self.object, '__name__', None)
     924            if classname:
     925                content = ViewList(
     926                    [_('alias of :class:`%s`') % classname], source='')
     927                ModuleLevelDocumenter.add_content(self, content,
     928                                                  no_docstring=True)
     929        else:
     930            ModuleLevelDocumenter.add_content(self, more_content)
     931
     932    def document_members(self, all_members=False):
     933        if self.doc_as_attr:
     934            return
     935        ModuleLevelDocumenter.document_members(self, all_members)
     936
     937
     938class ExceptionDocumenter(ClassDocumenter):
     939    """
     940    Specialized ClassDocumenter subclass for exceptions.
     941    """
     942    objtype = 'exception'
     943    member_order = 10
     944
     945    # needs a higher priority than ClassDocumenter
     946    priority = 10
     947
     948    @classmethod
     949    def can_document_member(cls, member, membername, isattr, parent):
     950        return isinstance(member, (type, ClassType)) and \
     951               issubclass(member, base_exception)
     952
     953
     954class DataDocumenter(ModuleLevelDocumenter):
     955    """
     956    Specialized Documenter subclass for data items.
     957    """
     958    objtype = 'data'
     959    member_order = 40
     960
     961    @classmethod
     962    def can_document_member(cls, member, membername, isattr, parent):
     963        return isinstance(parent, ModuleDocumenter) and isattr
     964
     965    def document_members(self, all_members=False):
     966        pass
     967
     968
     969class MethodDocumenter(ClassLevelDocumenter):
     970    """
     971    Specialized Documenter subclass for methods (normal, static and class).
     972    """
     973    objtype = 'method'
     974    member_order = 50
     975
     976    @classmethod
     977    def can_document_member(cls, member, membername, isattr, parent):
     978        # other attributes are recognized via the module analyzer
     979        return inspect.isroutine(member) and \
     980               not isinstance(parent, ModuleDocumenter)
     981
     982    def import_object(self):
     983        ret = ClassLevelDocumenter.import_object(self)
     984        if isinstance(self.object, classmethod) or \
     985               (isinstance(self.object, MethodType) and
     986                self.object.im_self is not None):
     987            self.directivetype = 'classmethod'
     988            # document class and static members before ordinary ones
     989            self.member_order = self.member_order - 1
     990        elif isinstance(self.object, FunctionType) or \
     991             (isinstance(self.object, BuiltinFunctionType) and
     992              self.object.__self__ is not None):
     993            self.directivetype = 'staticmethod'
     994            # document class and static members before ordinary ones
     995            self.member_order = self.member_order - 1
     996        else:
     997            self.directivetype = 'method'
     998        return ret
     999
     1000    def format_args(self):
     1001        if inspect.isbuiltin(self.object) or \
     1002               inspect.ismethoddescriptor(self.object):
     1003            # can never get arguments of a C function or method unless
     1004            # a function to do so is supplied
     1005            if self.env.config.autodoc_builtin_argspec:
     1006                argspec = self.env.config.autodoc_builtin_argspec(self.object)
     1007            else:
     1008                return None
     1009        else:
     1010            # The check above misses ordinary Python methods in Cython
     1011            # files.
     1012            try:
     1013                argspec = inspect.getargspec(self.object)
     1014            except TypeError:
     1015                if (inspect.ismethod(self.object) and
     1016                    self.env.config.autodoc_builtin_argspec):
     1017                    argspec = self.env.config.autodoc_builtin_argspec(self.object.im_func)
     1018                else:
     1019                    return None
     1020        if argspec[0] and argspec[0][0] in ('cls', 'self'):
     1021            del argspec[0][0]
     1022        return inspect.formatargspec(*argspec)
     1023
     1024    def document_members(self, all_members=False):
     1025        pass
     1026
     1027
     1028class AttributeDocumenter(ClassLevelDocumenter):
     1029    """
     1030    Specialized Documenter subclass for attributes.
     1031    """
     1032    objtype = 'attribute'
     1033    member_order = 60
     1034
     1035    @classmethod
     1036    def can_document_member(cls, member, membername, isattr, parent):
     1037        return (isdescriptor(member) and not
     1038                isinstance(member, (FunctionType, BuiltinFunctionType))) \
     1039               or (not isinstance(parent, ModuleDocumenter) and isattr)
     1040
     1041    def document_members(self, all_members=False):
     1042        pass
     1043
     1044
     1045class AutoDirective(Directive):
     1046    """
     1047    The AutoDirective class is used for all autodoc directives.  It dispatches
     1048    most of the work to one of the Documenters, which it selects through its
     1049    *_registry* dictionary.
     1050
     1051    The *_special_attrgetters* attribute is used to customize ``getattr()``
     1052    calls that the Documenters make; its entries are of the form ``type:
     1053    getattr_function``.
     1054
     1055    Note: When importing an object, all items along the import chain are
     1056    accessed using the descendant's *_special_attrgetters*, thus this
     1057    dictionary should include all necessary functions for accessing
     1058    attributes of the parents.
     1059    """
     1060    # a registry of objtype -> documenter class
     1061    _registry = {}
     1062
     1063    # a registry of type -> getattr function
     1064    _special_attrgetters = {}
     1065
     1066    # standard docutils directive settings
     1067    has_content = True
     1068    required_arguments = 1
     1069    optional_arguments = 0
     1070    final_argument_whitespace = True
     1071    # allow any options to be passed; the options are parsed further
     1072    # by the selected Documenter
     1073    option_spec = DefDict(identity)
     1074
     1075    def warn(self, msg):
     1076        self.warnings.append(self.reporter.warning(msg, line=self.lineno))
     1077
     1078    def run(self):
     1079        self.filename_set = set()  # a set of dependent filenames
     1080        self.reporter = self.state.document.reporter
     1081        self.env = self.state.document.settings.env
     1082        self.warnings = []
     1083        self.result = ViewList()
     1084
     1085        # find out what documenter to call
     1086        objtype = self.name[4:]
     1087        doc_class = self._registry[objtype]
     1088        # process the options with the selected documenter's option_spec
     1089        self.genopt = Options(assemble_option_dict(
     1090            self.options.items(), doc_class.option_spec))
     1091        # generate the output
     1092        documenter = doc_class(self, self.arguments[0])
     1093        documenter.generate(more_content=self.content)
     1094        if not self.result:
     1095            return self.warnings
     1096
     1097        # record all filenames as dependencies -- this will at least
     1098        # partially make automatic invalidation possible
     1099        for fn in self.filename_set:
     1100            self.env.note_dependency(fn)
     1101
     1102        # use a custom reporter that correctly assigns lines to source
     1103        # filename/description and lineno
     1104        old_reporter = self.state.memo.reporter
     1105        self.state.memo.reporter = AutodocReporter(self.result,
     1106                                                   self.state.memo.reporter)
     1107
     1108        if self.name == 'automodule':
     1109            node = nodes.section()
     1110            # necessary so that the child nodes get the right source/line set
     1111            node.document = self.state.document
     1112            nested_parse_with_titles(self.state, self.result, node)
     1113        else:
     1114            node = nodes.paragraph()
     1115            node.document = self.state.document
     1116            self.state.nested_parse(self.result, 0, node)
     1117        self.state.memo.reporter = old_reporter
     1118        return self.warnings + node.children
     1119
     1120
     1121def add_documenter(cls):
     1122    """Register a new Documenter."""
     1123    if not issubclass(cls, Documenter):
     1124        raise ExtensionError('autodoc documenter %r must be a subclass '
     1125                             'of Documenter' % cls)
     1126    # actually, it should be possible to override Documenters
     1127    #if cls.objtype in AutoDirective._registry:
     1128    #    raise ExtensionError('autodoc documenter for %r is already '
     1129    #                         'registered' % cls.objtype)
     1130    AutoDirective._registry[cls.objtype] = cls
     1131
     1132
     1133def setup(app):
     1134    # Override hard-coded 'from sphinx.ext import autodoc' in
     1135    # sphinx.application.
     1136    def add_autodocumenter(cls):
     1137        add_documenter(cls)
     1138        app.add_directive('auto' + cls.objtype, AutoDirective)
     1139
     1140    def add_autodoc_attrgetter(type, getter):
     1141        AutoDirective._special_attrgetters[type] = getter
     1142
     1143    app.add_autodocumenter = add_autodocumenter
     1144    app.add_autodoc_attrgetter = add_autodoc_attrgetter
     1145
     1146    app.add_autodocumenter(ModuleDocumenter)
     1147    app.add_autodocumenter(ClassDocumenter)
     1148    app.add_autodocumenter(ExceptionDocumenter)
     1149    app.add_autodocumenter(DataDocumenter)
     1150    app.add_autodocumenter(FunctionDocumenter)
     1151    app.add_autodocumenter(MethodDocumenter)
     1152    app.add_autodocumenter(AttributeDocumenter)
     1153
     1154    app.add_config_value('autoclass_content', 'class', True)
     1155    app.add_config_value('autodoc_member_order', 'alphabetic', True)
     1156    app.add_config_value('autodoc_builtin_argspec', None, True)
     1157    app.add_event('autodoc-process-docstring')
     1158    app.add_event('autodoc-process-signature')
     1159    app.add_event('autodoc-skip-member')