Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/doc/common/conf.py
8815 views
1
import sys, os, sphinx
2
from sage.env import SAGE_DOC
3
4
def get_doc_abspath(path):
5
"""
6
return the absolute path from a SAGE_DOC relative path
7
"""
8
return os.path.abspath(os.path.join(SAGE_DOC, path))
9
10
# If your extensions are in another directory, add it here. If the directory
11
# is relative to the documentation root, use get_doc_abspath to make it
12
# absolute, like shown here.
13
sys.path.append(get_doc_abspath('common'))
14
15
# General configuration
16
# ---------------------
17
18
# Add any Sphinx extension module names here, as strings. They can be extensions
19
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
20
extensions = ['inventory_builder', 'multidocs',
21
'sage_autodoc', 'sphinx.ext.graphviz',
22
'sphinx.ext.inheritance_diagram', 'sphinx.ext.todo',
23
'sphinx.ext.extlinks']
24
# We do *not* fully initialize intersphinx since we call it by hand
25
# in find_sage_dangling_links.
26
#, 'sphinx.ext.intersphinx']
27
28
29
# Add any paths that contain templates here, relative to this directory.
30
templates_path = [os.path.join(SAGE_DOC, 'common/templates'), 'templates']
31
32
# The suffix of source filenames.
33
source_suffix = '.rst'
34
35
# The master toctree document.
36
master_doc = 'index'
37
38
# General information about the project.
39
project = u""
40
copyright = u'2005--2011, The Sage Development Team'
41
42
# The version info for the project you're documenting, acts as replacement for
43
# |version| and |release|, also used in various other places throughout the
44
# built documents.
45
#
46
# The short X.Y version.
47
from sage.version import version
48
release = version
49
50
#version = '3.1.2'
51
# The full version, including alpha/beta/rc tags.
52
#release = '3.1.2'
53
54
# The language for content autogenerated by Sphinx. Refer to documentation
55
# for a list of supported languages.
56
#language = None
57
58
# There are two options for replacing |today|: either, you set today to some
59
# non-false value, then it is used:
60
#today = ''
61
# Else, today_fmt is used as the format for a strftime call.
62
#today_fmt = '%B %d, %Y'
63
64
# List of documents that shouldn't be included in the build.
65
#unused_docs = []
66
67
# List of directories, relative to source directory, that shouldn't be searched
68
# for source files.
69
exclude_trees = ['.build']
70
71
# The reST default role (used for this markup: `text`) to use for all documents.
72
default_role = 'math'
73
74
# If true, '()' will be appended to :func: etc. cross-reference text.
75
#add_function_parentheses = True
76
77
# If true, the current module name will be prepended to all description
78
# unit titles (such as .. function::).
79
#add_module_names = True
80
81
# If true, sectionauthor and moduleauthor directives will be shown in the
82
# output. They are ignored by default.
83
#show_authors = False
84
85
# The name of the Pygments (syntax highlighting) style to use. NOTE:
86
# This overrides a HTML theme's corresponding setting (see below).
87
pygments_style = 'sphinx'
88
89
# GraphViz includes dot, neato, twopi, circo, fdp.
90
graphviz_dot = 'dot'
91
inheritance_graph_attrs = { 'rankdir' : 'BT' }
92
inheritance_node_attrs = { 'height' : 0.5, 'fontsize' : 12, 'shape' : 'oval' }
93
inheritance_edge_attrs = {}
94
95
# Extension configuration
96
# -----------------------
97
98
# include the todos
99
todo_include_todos = True
100
101
102
# Cross-links to other project's online documentation.
103
# intersphinx_mapping = {'http://docs.python.org/': None}
104
#intersphinx_mapping = {'python': ('http://docs.python.org/',
105
# 'python-inv.txt')}
106
intersphinx_mapping = {
107
'http://docs.python.org/': get_doc_abspath('common/python.inv')}
108
109
def set_intersphinx_mappings(app):
110
"""
111
Add precompiled inventory (the objects.inv)
112
"""
113
refpath = get_doc_abspath('output/html/en/reference')
114
invpath = get_doc_abspath('output/inventory/en/reference')
115
if app.config.multidoc_first_pass == 1 or \
116
not (os.path.exists(refpath) and os.path.exists(invpath)):
117
app.config.intersphinx_mapping = {}
118
return
119
app.config.intersphinx_mapping = intersphinx_mapping
120
121
def add(subdoc=''):
122
src = os.path.join(refpath, subdoc) if subdoc else refpath
123
dst = os.path.join(invpath, subdoc, 'objects.inv')
124
app.config.intersphinx_mapping[src] = dst
125
126
add()
127
for directory in os.listdir(os.path.join(invpath)):
128
if os.path.isdir(os.path.join(invpath, directory)):
129
add(directory)
130
131
132
pythonversion = sys.version.split(' ')[0]
133
# Python and Sage trac ticket shortcuts. For example, :trac:`7549` .
134
135
# Sage trac ticket shortcuts. For example, :trac:`7549` .
136
extlinks = {
137
'python': ('http://docs.python.org/release/'+pythonversion+'/%s', ''),
138
'trac': ('http://trac.sagemath.org/%s', 'trac ticket #'),
139
'wikipedia': ('http://en.wikipedia.org/wiki/%s', 'Wikipedia article '),
140
'arxiv': ('http://arxiv.org/abs/%s', 'Arxiv '),
141
'oeis': ('http://oeis.org/%s', 'OEIS sequence '),
142
'doi': ('http://dx.doi.org/%s', 'doi:'),
143
'mathscinet': ('http://www.ams.org/mathscinet-getitem?mr=%s', 'MathSciNet ')
144
}
145
146
# By default document are not master.
147
multidocs_is_master = True
148
149
# Options for HTML output
150
# -----------------------
151
152
# HTML theme (e.g., 'default', 'sphinxdoc'). We use a custom Sage
153
# theme to set a Pygments style, stylesheet, and insert MathJax macros. See
154
# the directory doc/common/themes/sage/ for files comprising the custom Sage
155
# theme.
156
html_theme = 'sage'
157
158
# Theme options are theme-specific and customize the look and feel of
159
# a theme further. For a list of options available for each theme,
160
# see the documentation.
161
html_theme_options = {}
162
163
# Add any paths that contain custom themes here, relative to this directory.
164
html_theme_path = [os.path.join(SAGE_DOC, 'common/themes')]
165
166
# HTML style sheet NOTE: This overrides a HTML theme's corresponding
167
# setting.
168
#html_style = 'default.css'
169
170
# The name for this set of Sphinx documents. If None, it defaults to
171
# "<project> v<release> documentation".
172
#html_title = None
173
174
# A shorter title for the navigation bar. Default is the same as html_title.
175
#html_short_title = None
176
177
# The name of an image file (within the static path) to place at the top of
178
# the sidebar.
179
#html_logo = 'sagelogo-word.ico'
180
181
# The name of an image file (within the static path) to use as favicon of the
182
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
183
# pixels large.
184
html_favicon = 'favicon.ico'
185
186
# Add any paths that contain custom static files (such as style sheets) here,
187
# relative to this directory. They are copied after the builtin static files,
188
# so a file named "default.css" will overwrite the builtin "default.css".
189
html_static_path = [os.path.join(SAGE_DOC, 'common/static'), 'static']
190
191
# We use MathJax to build the documentation unless the environment
192
# variable SAGE_DOC_MATHJAX is set to "no" or "False". (Note that if
193
# the user does not set this variable, then the script sage-env sets
194
# it to "True".)
195
196
if (os.environ.get('SAGE_DOC_MATHJAX', 'no') != 'no'
197
and os.environ.get('SAGE_DOC_MATHJAX', 'no') != 'False'):
198
199
extensions.append('sphinx.ext.mathjax')
200
mathjax_path = 'MathJax.js?config=TeX-AMS_HTML-full,../mathjax_sage.js'
201
202
from sage.misc.latex_macros import sage_mathjax_macros
203
html_theme_options['mathjax_macros'] = sage_mathjax_macros()
204
205
from pkg_resources import Requirement, working_set
206
sagenb_path = working_set.find(Requirement.parse('sagenb')).location
207
mathjax_relative = os.path.join('sagenb','data','mathjax')
208
209
# It would be really nice if sphinx would copy the entire mathjax directory,
210
# (so we could have a _static/mathjax directory), rather than the contents of the directory
211
212
mathjax_static = os.path.join(sagenb_path, mathjax_relative)
213
html_static_path.append(mathjax_static)
214
exclude_patterns=['**/'+os.path.join(mathjax_relative, i) for i in ('docs', 'README*', 'test',
215
'unpacked', 'LICENSE')]
216
else:
217
extensions.append('sphinx.ext.pngmath')
218
219
220
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
221
# using the given strftime format.
222
#html_last_updated_fmt = '%b %d, %Y'
223
224
# If true, SmartyPants will be used to convert quotes and dashes to
225
# typographically correct entities.
226
#html_use_smartypants = True
227
228
# Custom sidebar templates, maps document names to template names.
229
#html_sidebars = {}
230
231
# Additional templates that should be rendered to pages, maps page names to
232
# template names.
233
#html_additional_pages = {}
234
235
# If false, no module index is generated.
236
#html_use_modindex = True
237
238
# A list of prefixes that are ignored for sorting the Python module index ( if
239
# this is set to ['foo.'], then foo.bar is shown under B, not F). Works only
240
# for the HTML builder currently.
241
modindex_common_prefix = ['sage.']
242
243
# If false, no index is generated.
244
#html_use_index = True
245
246
# If true, the index is split into individual pages for each letter.
247
html_split_index = True
248
249
# If true, the reST sources are included in the HTML build as _sources/<name>.
250
#html_copy_source = True
251
252
# If true, an OpenSearch description file will be output, and all pages will
253
# contain a <link> tag referring to it. The value of this option must be the
254
# base URL from which the finished HTML is served.
255
#html_use_opensearch = ''
256
257
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
258
#html_file_suffix = ''
259
260
# Output file base name for HTML help builder.
261
#htmlhelp_basename = ''
262
263
264
# Options for LaTeX output
265
# ------------------------
266
# See http://sphinx.pocoo.org/config.html#confval-latex_elements
267
latex_elements = {}
268
269
# The paper size ('letterpaper' or 'a4paper').
270
#latex_elements['papersize'] = 'letterpaper'
271
272
# The font size ('10pt', '11pt' or '12pt').
273
#latex_elements['pointsize'] = '10pt'
274
275
# Grouping the document tree into LaTeX files. List of tuples
276
# (source start file, target name, title, author, document class [howto/manual]).
277
latex_documents = []
278
279
# The name of an image file (relative to this directory) to place at the top of
280
# the title page.
281
#latex_logo = 'sagelogo-word.png'
282
283
# For "manual" documents, if this is true, then toplevel headings are parts,
284
# not chapters.
285
#latex_use_parts = False
286
287
# Additional stuff for the LaTeX preamble.
288
latex_elements['preamble'] = r"""
289
\usepackage{amsmath}
290
\usepackage{amssymb}
291
\usepackage{textcomp}
292
\usepackage{mathrsfs}
293
\DeclareUnicodeCharacter{01CE}{\capitalcaron a}
294
\DeclareUnicodeCharacter{0428}{cyrillic Sha}
295
"""
296
297
# Documents to append as an appendix to all manuals.
298
#latex_appendices = []
299
300
# If false, no module index is generated.
301
#latex_use_modindex = True
302
303
#####################################################
304
# add LaTeX macros for Sage
305
306
from sage.misc.latex_macros import sage_latex_macros
307
308
try:
309
pngmath_latex_preamble # check whether this is already defined
310
except NameError:
311
pngmath_latex_preamble = ""
312
313
for macro in sage_latex_macros():
314
# used when building latex and pdf versions
315
latex_elements['preamble'] += macro + '\n'
316
# used when building html version
317
pngmath_latex_preamble += macro + '\n'
318
319
#####################################################
320
321
def process_docstring_aliases(app, what, name, obj, options, docstringlines):
322
"""
323
Change the docstrings for aliases to point to the original object.
324
"""
325
basename = name.rpartition('.')[2]
326
if hasattr(obj, '__name__') and obj.__name__ != basename:
327
docstringlines[:] = ['See :obj:`%s`.' % name]
328
329
def process_directives(app, what, name, obj, options, docstringlines):
330
"""
331
Remove 'nodetex' and other directives from the first line of any
332
docstring where they appear.
333
"""
334
if len(docstringlines) == 0:
335
return
336
first_line = docstringlines[0]
337
directives = [ d.lower() for d in first_line.split(',') ]
338
if 'nodetex' in directives:
339
docstringlines.pop(0)
340
341
def process_docstring_cython(app, what, name, obj, options, docstringlines):
342
"""
343
Remove Cython's filename and location embedding.
344
"""
345
if len(docstringlines) <= 1:
346
return
347
348
first_line = docstringlines[0]
349
if first_line.startswith('File:') and '(starting at' in first_line:
350
#Remove the first two lines
351
docstringlines.pop(0)
352
docstringlines.pop(0)
353
354
def process_docstring_module_title(app, what, name, obj, options, docstringlines):
355
"""
356
Removes the first line from the beginning of the module's docstring. This
357
corresponds to the title of the module's documentation page.
358
"""
359
if what != "module":
360
return
361
362
#Remove any additional blank lines at the beginning
363
title_removed = False
364
while len(docstringlines) > 1 and not title_removed:
365
if docstringlines[0].strip() != "":
366
title_removed = True
367
docstringlines.pop(0)
368
369
#Remove any additional blank lines at the beginning
370
while len(docstringlines) > 1:
371
if docstringlines[0].strip() == "":
372
docstringlines.pop(0)
373
else:
374
break
375
376
skip_picklability_check_modules = [
377
#'sage.misc.nested_class_test', # for test only
378
'sage.misc.latex',
379
'sage.misc.explain_pickle',
380
'__builtin__',
381
]
382
383
def check_nested_class_picklability(app, what, name, obj, skip, options):
384
"""
385
Print a warning if pickling is broken for nested classes.
386
"""
387
import types
388
if hasattr(obj, '__dict__') and hasattr(obj, '__module__'):
389
# Check picklability of nested classes. Adapted from
390
# sage.misc.nested_class.modify_for_nested_pickle.
391
module = sys.modules[obj.__module__]
392
for (nm, v) in obj.__dict__.iteritems():
393
if (isinstance(v, (type, types.ClassType)) and
394
v.__name__ == nm and
395
v.__module__ == module.__name__ and
396
getattr(module, nm, None) is not v and
397
v.__module__ not in skip_picklability_check_modules):
398
# OK, probably this is an *unpicklable* nested class.
399
app.warn('Pickling of nested class %r is probably broken. '
400
'Please set __metaclass__ of the parent class to '
401
'sage.misc.nested_class.NestedClassMetaclass.' % (
402
v.__module__ + '.' + name + '.' + nm))
403
404
def skip_member(app, what, name, obj, skip, options):
405
"""
406
To suppress Sphinx warnings / errors, we
407
408
- Don't include [aliases of] builtins.
409
410
- Don't include the docstring for any nested class which has been
411
inserted into its module by
412
:class:`sage.misc.NestedClassMetaclass` only for pickling. The
413
class will be properly documented inside its surrounding class.
414
415
- Don't include
416
sagenb.notebook.twist.userchild_download_worksheets.zip.
417
418
- Optionally, check whether pickling is broken for nested classes.
419
420
- Optionally, include objects whose name begins with an underscore
421
('_'), i.e., "private" or "hidden" attributes, methods, etc.
422
423
Otherwise, we abide by Sphinx's decision. Note: The object
424
``obj`` is excluded (included) if this handler returns True
425
(False).
426
"""
427
if 'SAGE_CHECK_NESTED' in os.environ:
428
check_nested_class_picklability(app, what, name, obj, skip, options)
429
430
if getattr(obj, '__module__', None) == '__builtin__':
431
return True
432
433
if (hasattr(obj, '__name__') and obj.__name__.find('.') != -1 and
434
obj.__name__.split('.')[-1] != name):
435
return True
436
437
if name.find("userchild_download_worksheets.zip") != -1:
438
return True
439
440
if 'SAGE_DOC_UNDERSCORE' in os.environ:
441
if name.split('.')[-1].startswith('_'):
442
return False
443
444
return skip
445
446
def process_dollars(app, what, name, obj, options, docstringlines):
447
r"""
448
Replace dollar signs with backticks.
449
See sage.misc.sagedoc.process_dollars for more information
450
"""
451
if len(docstringlines) > 0 and name.find("process_dollars") == -1:
452
from sage.misc.sagedoc import process_dollars as sagedoc_dollars
453
s = sagedoc_dollars("\n".join(docstringlines))
454
lines = s.split("\n")
455
for i in range(len(lines)):
456
docstringlines[i] = lines[i]
457
458
def process_inherited(app, what, name, obj, options, docstringlines):
459
"""
460
If we're including inherited members, omit their docstrings.
461
"""
462
if not options.get('inherited-members'):
463
return
464
465
if what in ['class', 'data', 'exception', 'function', 'module']:
466
return
467
468
name = name.split('.')[-1]
469
470
if what == 'method' and hasattr(obj, 'im_class'):
471
if name in obj.im_class.__dict__.keys():
472
return
473
474
if what == 'attribute' and hasattr(obj, '__objclass__'):
475
if name in obj.__objclass__.__dict__.keys():
476
return
477
478
for i in xrange(len(docstringlines)):
479
docstringlines.pop()
480
481
dangling_debug = False
482
483
def debug_inf(app, message):
484
if dangling_debug: app.info(message)
485
486
def call_intersphinx(app, env, node, contnode):
487
"""
488
Call intersphinx and work around its misshandling of relative links
489
"""
490
debug_inf(app, "???? Trying intersphinx for %s"%node['reftarget'])
491
builder = app.builder
492
res = sphinx.ext.intersphinx.missing_reference(
493
app, env, node, contnode)
494
if res: #workaround intersphinx misshandling of relative links
495
# useful for debugging
496
# import pdb
497
# pdb.set_trace()
498
if res['refuri'].startswith(SAGE_DOC):
499
here = os.path.dirname(os.path.join(builder.outdir,
500
node['refdoc']))
501
res['refuri'] = os.path.relpath(res['refuri'], here)
502
debug_inf(app, "++++ Found at %s"%res['refuri'])
503
else:
504
debug_inf(app, "---- Intersphinx: %s not Found"%node['reftarget'])
505
return res
506
507
def find_sage_dangling_links(app, env, node, contnode):
508
"""
509
Try to find dangling link in local module imports or all.py.
510
"""
511
debug_inf(app, "==================== find_sage_dangling_links ")
512
513
reftype = node['reftype']
514
reftarget = node['reftarget']
515
try:
516
doc = node['refdoc']
517
except KeyError:
518
debug_inf(app, "-- no refdoc in node %s"%node)
519
return None
520
521
debug_inf(app, "Searching %s from %s"%(reftarget, doc))
522
523
# Workaround: in Python's doc 'object', 'list', ... are documented as a
524
# function rather than a class
525
if reftarget in base_class_as_func and reftype == 'class':
526
node['reftype'] = 'func'
527
528
res = call_intersphinx(app, env, node, contnode)
529
if res:
530
debug_inf(app, "++ DONE %s"%(res['refuri']))
531
return res
532
533
if node.get('refdomain') != 'py': # not a python file
534
return None
535
536
try:
537
module = node['py:module']
538
cls = node['py:class']
539
except KeyError:
540
debug_inf(app, "-- no module or class for :%s:%s"%(reftype, reftarget))
541
return None
542
543
basename = reftarget.split(".")[0]
544
try:
545
target_module = getattr(sys.modules['sage.all'], basename).__module__
546
except AttributeError:
547
debug_inf(app, "-- %s not found in sage.all"%(basename))
548
return None
549
if target_module is None:
550
target_module = ""
551
debug_inf(app, "?? found in None !!!")
552
553
debug_inf(app, "++ found %s using sage.all in %s"%(basename, target_module))
554
555
newtarget = target_module+'.'+reftarget
556
node['reftarget'] = newtarget
557
558
# adapted from sphinx/domains/python.py
559
builder = app.builder
560
searchmode = node.hasattr('refspecific') and 1 or 0
561
matches = builder.env.domains['py'].find_obj(
562
builder.env, module, cls, newtarget, reftype, searchmode)
563
if not matches:
564
debug_inf(app, "?? no matching doc for %s"%newtarget)
565
return call_intersphinx(app, env, node, contnode)
566
elif len(matches) > 1:
567
env.warn(target_module,
568
'more than one target found for cross-reference '
569
'%r: %s' % (newtarget,
570
', '.join(match[0] for match in matches)),
571
node.line)
572
name, obj = matches[0]
573
debug_inf(app, "++ match = %s %s"%(name, obj))
574
575
from docutils import nodes
576
newnode = nodes.reference('', '', internal=True)
577
if name == target_module:
578
newnode['refid'] = name
579
else:
580
newnode['refuri'] = builder.get_relative_uri(node['refdoc'], obj[0])
581
newnode['refuri'] += '#' + name
582
debug_inf(app, "++ DONE at URI %s"%(newnode['refuri']))
583
newnode['reftitle'] = name
584
newnode.append(contnode)
585
return newnode
586
587
# lists of basic Python class which are documented as functions
588
base_class_as_func = [
589
'bool', 'complex', 'dict', 'file', 'float',
590
'frozenset', 'int', 'list', 'long', 'object',
591
'set', 'slice', 'str', 'tuple', 'type', 'unicode', 'xrange']
592
593
# Nit picky option configuration: Put here broken links we want to ignore. For
594
# link to the Python documentation several links where broken because there
595
# where class listed as functions. Expand the list 'base_class_as_func'
596
# above instead of marking the link as broken.
597
nitpick_ignore = (
598
('py:class', 'twisted.web2.resource.Resource'),
599
('py:class', 'twisted.web2.resource.PostableResource'))
600
601
def nitpick_patch_config(app):
602
"""
603
Patch the default config for nitpicky
604
605
Calling path_config ensure that nitpicky is not considered as a Sphinx
606
environment variable but rather as a Sage environment variable. As a
607
consequence, changing it doesn't force the recompilation of the entire
608
documentation.
609
"""
610
app.config.values['nitpicky'] = (False, 'sage')
611
app.config.values['nitpick_ignore'] = ([], 'sage')
612
613
from sage.misc.sageinspect import sage_getargspec
614
autodoc_builtin_argspec = sage_getargspec
615
616
def setup(app):
617
app.connect('autodoc-process-docstring', process_docstring_cython)
618
app.connect('autodoc-process-docstring', process_directives)
619
app.connect('autodoc-process-docstring', process_docstring_module_title)
620
app.connect('autodoc-process-docstring', process_dollars)
621
app.connect('autodoc-process-docstring', process_inherited)
622
app.connect('autodoc-skip-member', skip_member)
623
624
# When building the standard docs, app.srcdir is set to SAGE_DOC +
625
# 'LANGUAGE/DOCNAME', but when doing introspection, app.srcdir is
626
# set to a temporary directory. We don't want to use intersphinx,
627
# etc., when doing introspection.
628
if app.srcdir.startswith(SAGE_DOC):
629
app.add_config_value('intersphinx_mapping', {}, False)
630
app.add_config_value('intersphinx_cache_limit', 5, False)
631
# We do *not* fully initialize intersphinx since we call it by hand
632
# in find_sage_dangling_links.
633
# app.connect('missing-reference', missing_reference)
634
app.connect('missing-reference', find_sage_dangling_links)
635
import sphinx.ext.intersphinx
636
app.connect('builder-inited', set_intersphinx_mappings)
637
app.connect('builder-inited', sphinx.ext.intersphinx.load_mappings)
638
app.connect('builder-inited', nitpick_patch_config)
639
640
641