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