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