Ticket #6495: trac_6495-part3-the-remaining.patch

File trac_6495-part3-the-remaining.patch, 34.3 KB (added by hivert, 7 years ago)
  • doc/common/builder.py

    # HG changeset patch
    # User Florent Hivert <Florent.Hivert@univ-rouen.fr>
    # Date 1336416039 -7200
    # Node ID 4d6d27806033232f68c18551b2e271bb177824e6
    # Parent  ff684d217ab372f611772290497ebe4cf1b9c5f6
    #6495: Build the reference manual incrementally
    - Add a builder for generating object.inv and pickle files.
    - Add an extension multidocs which merge the various indexes.
    
    diff --git a/doc/common/builder.py b/doc/common/builder.py
    a b def copytree(src, dst, symlinks=False, i 
    8585##########################################
    8686#      Parallel Building Ref Manual      #
    8787##########################################
    88 
    89 def build_ref_doc(doc, lang, format, output_dir, *args, **kwds):
    90     # Build the reference manual for doc
    91     static_dir = os.path.join(output_dir, 'reference', '_static')
    92     bad_static = os.path.join(output_dir, doc, '_static')
    93     # We need to remove the link to "_static" before generating the
    94     # documentation, because the html doc builder writes to the
    95     # _static directory.
    96     if (os.path.isdir(static_dir) and os.path.isdir(bad_static)
    97         and os.path.islink(bad_static)):
    98         os.remove(bad_static)
     88def build_ref_doc(doc, lang, format, *args, **kwds):
    9989    getattr(ReferenceSubBuilder(doc, lang), format)(*args, **kwds)
    100     # The standard Sphinx html build puts a copy of the "static"
    101     # directory in reference/doc/_static.  For the reference manual,
    102     # these are all identical to reference/_static, so delete the
    103     # directory reference/doc/_static and replace it with a link to
    104     # reference/_static.  This saves hundreds of megabytes of disk
    105     # space.
    106     if (os.path.isdir(static_dir) and os.path.isdir(bad_static)
    107         and not os.path.islink(bad_static)):
    108         shutil.rmtree(bad_static)
    109     if os.path.isdir(static_dir):
    110         os.symlink(static_dir, bad_static)
    11190
    11291##########################################
    11392#             Builders                   #
    11493##########################################
     94
    11595def builder_helper(type):
    11696    """
    11797    Returns a function which builds the documentation for
    class DocBuilder(object): 
    171151            sage: b._output_dir('html')
    172152            '.../devel/sage/doc/output/html/en/tutorial'
    173153        """
     154        if type == "inventory": # put inventories in the html tree
     155            type = "html"
    174156        return mkdir(os.path.join(SAGE_DOC, "output", type, self.lang, self.name))
    175157
    176158    def _doctrees_dir(self):
    class DocBuilder(object): 
    197179            sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
    198180            sage: b = builder.DocBuilder('tutorial')
    199181            sage: b._output_formats()
    200             ['changes', 'html', 'htmlhelp', 'json', 'latex', 'linkcheck', 'pickle', 'web']
     182            ['changes', 'html', 'htmlhelp', 'inventory', 'json', 'latex', 'linkcheck', 'pickle', 'web']
    201183
    202184        """
    203185        #Go through all the attributes of self and check to
    class DocBuilder(object): 
    249231    latex = builder_helper('latex')
    250232    changes = builder_helper('changes')
    251233    linkcheck = builder_helper('linkcheck')
     234    # import the customized builder for object.inv files
     235    inventory = builder_helper('inventory')
     236
     237##########################################
     238#      Parallel Building Ref Manual      #
     239##########################################
     240def build_other_doc(document, name, *args, **kwds):
     241    logger.warning("\nBuilding %s.\n" % document)
     242    getattr(get_builder(document), name)(*args, **kwds)
    252243
    253244
    254245class AllBuilder(object):
    class AllBuilder(object): 
    270261        This is the function which goes through all of the documents
    271262        and does the actual building.
    272263        """
     264        import time
     265        start = time.time()
    273266        docs = self.get_all_documents()
    274267        refs = [x for x in docs if x.endswith('reference')]
    275268        others = [x for x in docs if not x.endswith('reference')]
    276         for document in others:
    277             logger.warning("\nBuilding %s.\n" % document)
    278             getattr(get_builder(document), name)(*args, **kwds)
    279         # Build the reference manual twice to resolve references.
    280         # That is, build once to construct the intersphinx inventory
    281         # files, and then build the second time for real.  So the
    282         # first build should be as fast as possible; thus do an html
    283         # build first.
     269        # Build the reference manual twice to resolve references.  That is,
     270        # build once with the inventory builder to construct the intersphinx
     271        # inventory files, and then build the second time for real.  So the
     272        # first build should be as fast as possible;
    284273        logger.warning("\nBuilding reference manual, first pass.\n")
    285274        global ALLSPHINXOPTS
    286         ALLSPHINXOPTS += ' -Q '
     275        #ALLSPHINXOPTS += ' -Q -D multidoc_first_pass=1'
     276        ALLSPHINXOPTS += ' -D multidoc_first_pass=1'
    287277        for document in refs:
    288             getattr(get_builder(document), 'html')(*args, **kwds)
     278            getattr(get_builder(document), 'inventory')(*args, **kwds)
    289279        logger.warning("Building reference manual, second pass.\n")
     280        ALLSPHINXOPTS = ALLSPHINXOPTS.replace(
     281            'multidoc_first_pass=1', 'multidoc_first_pass=0')
    290282        ALLSPHINXOPTS = ALLSPHINXOPTS.replace('-Q', '-q') + ' -a '
    291283        for document in refs:
    292284            getattr(get_builder(document), name)(*args, **kwds)
    293285
     286        # build the other documents in parallel
     287        from multiprocessing import Pool, cpu_count
     288        pool = Pool(int(os.environ.get('SAGE_NUM_THREADS', 1)))
     289        for document in others:
     290            pool.apply_async(build_other_doc,
     291                             (document, name)+args, kwds)
     292        pool.close()
     293        pool.join()
     294        logger.warning("Elapsed time = %s."%(time.time()-start))
     295        logger.warning("Done compiling the doc !")
     296
    294297    def get_all_documents(self):
    295298        """
    296299        Returns a list of all of the documents. A document is a directory within one of
    class ReferenceBuilder(AllBuilder): 
    387390            sage: b._output_dir('html')
    388391            '.../devel/sage/doc/output/html/en/reference'
    389392        """
     393        if type == "inventory": # put inventories in the html tree
     394            type = "html"
    390395        return mkdir(os.path.join(SAGE_DOC, "output", type, lang, self.name))
    391396
    392397    def _wrapper(self, format, *args, **kwds):
    class ReferenceBuilder(AllBuilder): 
    398403            refdir = os.path.join(SAGE_DOC, lang, self.name)
    399404            if not os.path.exists(refdir):
    400405                continue
    401 
    402406            output_dir = self._output_dir(format, lang)
    403             getattr(DocBuilder(self.name, lang), format)(*args, **kwds)
    404 
    405407            from multiprocessing import Pool, cpu_count
    406408            # Determine the number of threads from the environment variable
    407409            # SAGE_NUM_THREADS.
    408410            pool = Pool(int(os.environ.get('SAGE_NUM_THREADS', 1)))
     411
    409412            for doc in self.get_all_documents(refdir):
    410413                pool.apply_async(build_ref_doc,
    411                                  (doc, lang, format,
    412                                   os.path.split(output_dir)[0]) + args, kwds)
     414                                 (doc, lang, format) + args, kwds)
    413415            pool.close()
    414416            pool.join()
    415             if format == 'html':
    416                 # html build: combine the todo lists from the
    417                 # different modules.
    418                 todofile = os.path.join(output_dir, 'todolist', 'index.html')
    419                 old = open(todofile).read()
    420                 note = "The combined to do list is only available in the html version of the reference manual."
    421                 preamble = old.find(note)
    422                 postamble = preamble + len(note)
    423                 if preamble != -1:
    424                     old_todofile = os.path.join(output_dir, 'todolist', 'index-old.html')
    425                     shutil.move(todofile, old_todofile)
    426                     new = open(todofile, 'w')
    427                     new.write(old[:preamble])
    428                     for f in os.listdir(output_dir):
    429                         index = os.path.join(output_dir, f, 'index.html')
    430                         if (f != 'todolist' and os.path.exists(index)):
    431                             html = open(index).read()
    432                             start = html.find('<div class="admonition-todo')
    433                             end = html.find('<div class="section" id="indices-and-tables">')
    434                             if start != -1:
    435                                 html = html[start:end].replace('sage/%s' %f,
    436                                                                '../%s/sage/%s' % (f, f))
    437                                 new.write(html)
    438                     new.write(old[postamble:])
    439                     new.close()
     417            # The html refman must be build at the end to ensure correct
     418            # merging of indexes and inventories.
     419            getattr(DocBuilder(self.name, lang), format)(*args, **kwds)
    440420
    441                 logger.warning('''
    442 Build finished.  The Sage reference manual can be found in
    443 
    444   %s
    445 ''' % (os.path.join(output_dir, 'index.html')))
    446421            # PDF: we need to build master index file which lists all
    447422            # of the PDF file.  So we create an html file, based on
    448423            # the file index.html from the "website" target.
    for a webpage listing all of the documen 
    542517        Returns a list of all reference manual components to build.
    543518        We add a component name if it's a subdirectory of the manual's
    544519        directory and contains a file named 'index.rst'.
     520
     521        EXAMPLES::
     522
     523            sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
     524            sage: b = builder.ReferenceBuilder('reference')
     525            sage: refdir = os.path.join(os.environ['SAGE_DOC'], 'en', b.name)
     526            sage: b.get_all_documents(refdir)
    545527        """
    546528        documents = []
    547529
    548530        for doc in os.listdir(refdir):
    549531            if os.path.exists(os.path.join(refdir, doc, 'index.rst')):
    550532                documents.append(os.path.join(self.name, doc))
    551        
    552         return documents
     533
     534        return sorted(documents)
    553535
    554536
    555537class ReferenceSubBuilder(DocBuilder):
    class ReferenceSubBuilder(DocBuilder): 
    684666        except IOError as err:
    685667            logger.debug("Failed to open Sphinx environment: %s", err)
    686668            pass
    687                                            
     669
    688670    def update_mtimes(self):
    689671        """
    690672        Updates the modification times for ReST files in the Sphinx
    class ReferenceSubBuilder(DocBuilder): 
    853835
    854836            sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
    855837            sage: import builder
    856             sage: builder.ReferenceBuilder("reference").auto_rest_filename("sage.combinat.partition")
     838            sage: builder.ReferenceSubBuilder("reference").auto_rest_filename("sage.combinat.partition")
    857839            '.../devel/sage/doc/en/reference/sage/combinat/partition.rst'
    858840        """
    859841        return self.dir + os.path.sep + module_name.replace('.',os.path.sep) + '.rst'
  • doc/common/conf.py

    diff --git a/doc/common/conf.py b/doc/common/conf.py
    a b sys.path.append(get_doc_abspath('common' 
    1919
    2020# Add any Sphinx extension module names here, as strings. They can be extensions
    2121# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
    22 extensions = ['sage_autodoc',  'sphinx.ext.graphviz',
     22extensions = ['inventory_builder', 'multidocs',
     23              'sage_autodoc',  'sphinx.ext.graphviz',
    2324              'sphinx.ext.inheritance_diagram', 'sphinx.ext.todo',
    2425              'sphinx.ext.extlinks']
    2526# We do *not* fully initialize intersphinx since we call it by hand
    if 'SAGE_DOC_JSMATH' in os.environ: 
    206207# If false, no module index is generated.
    207208#html_use_modindex = True
    208209
     210# A list of prefixes that are ignored for sorting the Python module index ( if
     211# this is set to ['foo.'], then foo.bar is shown under B, not F). Works only
     212# for the HTML builder currently.
     213modindex_common_prefix = ['sage.']
     214
    209215# If false, no index is generated.
    210216#html_use_index = True
    211217
  • new file doc/common/inventory_builder.py

    diff --git a/doc/common/inventory_builder.py b/doc/common/inventory_builder.py
    new file mode 100644
    - +  
     1# -*- coding: utf-8 -*-
     2"""
     3    inventory builder
     4    ~~~~~~~~~~~~~~~~~
     5
     6    A customized HTML builder which only generate intersphinx "object.inv"
     7    inventory files and pickle files. The documentation files are not writen.
     8"""
     9from sphinx.builders.html import StandaloneHTMLBuilder
     10from sphinx.util.console import bold
     11
     12class InventoryBuilder(StandaloneHTMLBuilder):
     13    """
     14    A customized HTML builder which only generate intersphinx "object.inv"
     15    inventory files and pickle files. The documentation files are not writen.
     16    """
     17    name = "inventory"
     18
     19    def write_doc(self, docname, doctree):
     20        """
     21        Don't write any doc
     22        """
     23
     24    def finish(self):
     25        """
     26        Only write the inventory files.
     27        """
     28        self.write_buildinfo()
     29        self.dump_inventory()
     30
     31    def removed_method_error(self):
     32        """
     33        Raise an error if this method is called.
     34
     35        This is just for making sure that some writer methods are indeed
     36        deactivated.
     37        """
     38        raise RuntimeError, "This function souldn't be called in \"%s\" builder"%(self.name)
     39
     40    copy_image_files = removed_method_error
     41    copy_download_files = removed_method_error
     42    copy_static_files = removed_method_error
     43    handle_finish = removed_method_error
     44
     45def setup(app):
     46    app.add_builder(InventoryBuilder)
     47
  • new file doc/common/multidocs.py

    diff --git a/doc/common/multidocs.py b/doc/common/multidocs.py
    new file mode 100644
    - +  
     1# -*- coding: utf-8 -*-
     2"""
     3    multi documentations in Sphinx
     4    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     5
     6    The goal of this extension is to manage a multi documentation in Sphinx.
     7    To be able to compile Sage huge documentation in parallel, the
     8    documentation is cut in a bunch of independent documentations called a
     9    "subdoc", which are compiled separately. There is a master document which
     10    points to all the subdocs. The intersphinx extension ensure that the
     11    cross-link between the subdocs are correctly resolved. However some work
     12    is needed to build a global index. This is the goal of multidocs.
     13
     14    More precisely this extension ensure the correct merging of
     15    - the todo list if this extension is activated;
     16    - the python indexes;
     17    - the list of python modules;
     18    - the javascript index;
     19    - the citations.
     20"""
     21import cPickle, os, sys
     22import sphinx
     23from sphinx.util.console import bold
     24
     25
     26CITE_FILENAME = 'citations.pickle'
     27
     28
     29def merge_environment(app, env):
     30    """
     31    Merges the following attributes of the sub-docs environment into the main
     32    environment:
     33    - todo_all_todos              # ToDo's
     34    - indexentries                # global python index
     35    - all_docs                    # needed by the js index
     36    - citations                   # citations
     37
     38    - domaindata['py']['modules'] # list of python modules
     39    """
     40    app.info(bold('Merging environment/index files...'))
     41    for curdoc in app.env.config.multidocs_subdoc_list:
     42        app.info("    %s:"%curdoc, nonl=1)
     43        docenv = get_env(app, curdoc)
     44        if docenv is not None:
     45            fixpath = lambda path: os.path.join(curdoc, path)
     46            app.info(" %s todos, %s index, %s citations"%(
     47                    len(docenv.todo_all_todos),
     48                    len(docenv.indexentries),
     49                    len(docenv.citations)
     50                    ), nonl=1)
     51
     52            # merge the todo links
     53            for dct in docenv.todo_all_todos:
     54                dct['docname']=fixpath(dct['docname'])
     55            env.todo_all_todos += docenv.todo_all_todos
     56            # merge the html index links
     57            newindex = {}
     58            for ind in docenv.indexentries:
     59                if ind.startswith('sage/'):
     60                    newind = fixpath(ind)
     61                    newindex[newind] = docenv.indexentries[ind]
     62                else:
     63                    newindex[ind] = docenv.indexentries[ind]
     64            env.indexentries.update(newindex)
     65            # merge the all_docs links, needed by the js index
     66            newalldoc = {}
     67            for ind in docenv.all_docs:
     68                newalldoc[fixpath(ind)]=docenv.all_docs[ind]
     69            env.all_docs.update(newalldoc)
     70            # needed by env.check_consistency (sphinx.environement, line 1734)
     71            for ind in newalldoc:
     72                env.metadata[ind] = {}
     73            # merge the citations
     74            newcite = {}
     75            for ind, (path, tag) in docenv.citations.iteritems():
     76                # TODO: Warn on conflicts
     77                newcite[ind]=(fixpath(path), tag)
     78            env.citations.update(newcite)
     79            # merge the py:module indexes
     80            newmodules = {}
     81            for ind,(modpath,v1,v2,v3) in (
     82                docenv.domaindata['py']['modules'].iteritems()):
     83                newmodules[ind] = (fixpath(modpath),v1,v2,v3)
     84            env.domaindata['py']['modules'].update(newmodules)
     85            app.info(", %s modules"%(len(newmodules)))
     86    app.info('... done (%s todos, %s index, %s citations, %s modules)'%(
     87            len(env.todo_all_todos),
     88            len(env.indexentries),
     89            len(env.citations),
     90            len(env.domaindata['py']['modules'])))
     91    write_citations(app, env.citations)
     92
     93def get_env(app, curdoc):
     94    """
     95    Get the environement of a sub-doc from the pickle
     96    """
     97    from sphinx.application import ENV_PICKLE_FILENAME
     98    filename = os.path.join(
     99        app.env.doctreedir, curdoc, ENV_PICKLE_FILENAME)
     100    try:
     101        f = open(filename, 'rb')
     102    except IOError:
     103        app.info("")
     104        app.warn("Unable to fetch %s "%filename)
     105        return None
     106    docenv = cPickle.load(f)
     107    f.close()
     108    return docenv
     109
     110def merge_js_index(app):
     111    """
     112    Merge the JS indexes of the sub-docs into the main JS index
     113    """
     114    app.info('')
     115    app.info(bold('Merging js index files...'))
     116    mapping = app.builder.indexer._mapping
     117    for curdoc in app.env.config.multidocs_subdoc_list:
     118        app.info("    %s:"%curdoc, nonl=1)
     119        fixpath = lambda path: os.path.join(curdoc, path)
     120        index = get_js_index(app, curdoc)
     121        if index is not None:
     122            # merge the mappings
     123            app.info(" %s js index entries"%(len(index._mapping)))
     124            for (ref, locs) in index._mapping.iteritems():
     125                newmapping = set(map(fixpath, locs))
     126                if ref in mapping:
     127                    newmapping = mapping[ref] | newmapping
     128                mapping[unicode(ref)] = newmapping
     129            # merge the titles
     130            titles = app.builder.indexer._titles
     131            for (res, title) in index._titles.iteritems():
     132                titles[fixpath(res)] = title
     133            # TODO: merge indexer._objtypes, indexer._objnames as well
     134
     135            # Setup source symbolic links
     136            dest = os.path.join(app.outdir, "_sources", curdoc)
     137            if not os.path.exists(dest):
     138                os.symlink(os.path.join("..", curdoc, "_sources"), dest)
     139    app.info('... done (%s js index entries)'%(len(mapping)))
     140    app.info(bold('Writing js search indexes...'), nonl=1)
     141    return [] # no extra page to setup
     142
     143def get_js_index(app, curdoc):
     144    """
     145    Get the JS index of a sub-doc from the file
     146    """
     147    from sphinx.search import IndexBuilder, languages
     148    # FIXME: find the correct lang
     149    indexer = IndexBuilder(app.env, 'en',
     150                           app.config.html_search_options)
     151    indexfile = os.path.join(app.outdir, curdoc, 'searchindex.js')
     152    try:
     153        f = open(indexfile, 'rb')
     154    except IOError:
     155        app.info("")
     156        app.warn("Unable to fetch %s "%indexfile)
     157        return None
     158    indexer.load(f, sphinx.search.js_index)
     159    f.close()
     160    return indexer
     161
     162
     163mustbefixed = ['search', 'genindex', 'genindex-all'
     164               'py-modindex', 'searchindex.js']
     165def fix_path_html(app, pagename, templatename, ctx, event_arg):
     166    """
     167    Fixes the context so that the files
     168    - search.html
     169    - genindex.html
     170    - py-modindex.html
     171    points to the right place, that is in
     172        reference/
     173    instead of
     174        reference/subdocument
     175    """
     176    # sphinx/builder/html.py line 702
     177    # def pathto(otheruri, resource=False,
     178    #            baseuri=self.get_target_uri(pagename)):
     179    old_pathto = ctx['pathto']
     180    def sage_pathto(otheruri, *args, **opts):
     181        if otheruri in mustbefixed:
     182            otheruri = os.path.join("..", otheruri)
     183        return old_pathto(otheruri, *args, **opts)
     184    ctx['pathto'] = sage_pathto
     185
     186
     187def write_citations(app, citations):
     188    """
     189    Pickle the citation in a file
     190    """
     191    import cPickle
     192    file = open(os.path.join(app.outdir, CITE_FILENAME), 'wb')
     193    cPickle.dump(citations, file)
     194    file.close()
     195    app.info("Saved pickle file: %s"%CITE_FILENAME)
     196
     197
     198def fetch_citation(app, env):
     199    """
     200    Fetch the global citation index from the refman to allows for cross
     201    references.
     202    """
     203    app.builder.info(bold('loading cross citations... '), nonl=1)
     204    filename = os.path.join(app.outdir, '..', CITE_FILENAME)
     205    if not os.path.exists(filename):
     206        return
     207    import cPickle
     208    file = open(filename, 'rb')
     209    try:
     210        cache = cPickle.load(file)
     211    except:
     212        app.warn("Cache file '%s' is corrupted; ignoring it..."% filename)
     213        return
     214    else:
     215        app.builder.info("done (%s citations)."%len(cache))
     216    finally:
     217        file.close()
     218    cite = env.citations
     219    for ind, (path, tag) in cache.iteritems():
     220        if ind not in cite: # don't override local citation
     221            cite[ind]=(os.path.join("..", path), tag)
     222
     223def init_subdoc(app):
     224    """
     225    Init the merger depending on if we are compiling a subdoc or the master
     226    doc itself.
     227    """
     228    if app.config.multidocs_is_master:
     229        app.info(bold("Compiling the master document"))
     230        app.connect('env-updated', merge_environment)
     231        app.connect('html-collect-pages', merge_js_index)
     232    else:
     233        app.info(bold("Compiling a sub-document"))
     234        app.connect('env-updated', fetch_citation)
     235        app.connect('html-page-context', fix_path_html)
     236
     237        # Monkey patch copy_static_files to make a symlink to "../"
     238        def link_static_files():
     239            """
     240            Instead of copying static files, make a link to the master static file.
     241            See sphinx/builder/html.py line 536::
     242
     243                class StandaloneHTMLBuilder(Builder):
     244                [...]
     245                    def copy_static_files(self):
     246                    [...]
     247            """
     248            app.builder.info(bold('linking _static directory.'))
     249            static_dir = os.path.join(app.builder.outdir, '_static')
     250            master_static_dir = os.path.join('..', '_static')
     251            if not os.path.isdir(static_dir):
     252                os.symlink(master_static_dir, static_dir)
     253
     254        app.builder.copy_static_files = link_static_files
     255
     256    if app.config.multidoc_first_pass == 1:
     257        app.config.intersphinx_mapping = {}
     258
     259
     260def setup(app):
     261    app.add_config_value('multidocs_is_master', True, True)
     262    app.add_config_value('multidocs_subdoc_list', [], True)
     263    app.add_config_value('multidoc_first_pass', 0, False)   # 1 = deactivate the loading of the inventory
     264    app.connect('builder-inited', init_subdoc)
  • doc/en/reference/conf.py

    diff --git a/doc/en/reference/conf.py b/doc/en/reference/conf.py
    a b latex_elements['preamble'] += r''' 
    6161#Ignore all .rst in the _sage subdirectory
    6262exclude_trees = exclude_trees + ['_sage']
    6363
    64 # List of directories, relative to source directory, that shouldn't be
    65 # searched for source files.
    66 exclude_trees = exclude_trees + [
     64multidocs_is_master = True
     65
     66# List of subdocs
     67multidocs_subdoc_list = [
    6768    'algebras',
    6869    'arithgroup',
    6970    'calculus',
    exclude_trees = exclude_trees + [ 
    100101    'notebook',
    101102    'number_fields',
    102103    'numerical',
    103     'options',
    104104    'padics',
    105105    'parallel',
    106106    'plane_curves',
    exclude_trees = exclude_trees + [ 
    114114    'rings',
    115115    'rings_numerical',
    116116    'rings_standard',
    117     'sage',
    118     'sagenb',
    119117    'schemes',
    120118    'semirings',
    121119    'stats',
    122120    'structure',
    123     'tensor',
    124     'todolist'
     121    'tensor'
    125122    ]
     123
     124# List of directories, relative to source directory, that shouldn't be
     125# searched for source files.
     126exclude_trees += multidocs_subdoc_list + [
     127    'sage', 'sagenb', 'options'
     128    ]
  • doc/en/reference/conf_sub.py

    diff --git a/doc/en/reference/conf_sub.py b/doc/en/reference/conf_sub.py
    a b latex_documents = [ 
    6969
    7070#Ignore all .rst in the _sage subdirectory
    7171exclude_trees = exclude_trees + ['_sage']
     72
     73multidocs_is_master = False
  • doc/en/reference/footer.txt

    diff --git a/doc/en/reference/footer.txt b/doc/en/reference/footer.txt
    a b  
    1 
    2 .. todolist::
    3 
    41Indices and Tables
    52==================
    63
    7 .. toctree::
    8    :maxdepth: 1
    9 
    10 * :ref:`genindex`
    11 * :ref:`modindex`
    12 * :ref:`search`
     4* `Index <../genindex.html>`_
     5* `Module Index <../py-modindex.html>`_
     6* `Search Page <../search.html>`_
  • doc/en/reference/index.rst

    diff --git a/doc/en/reference/index.rst b/doc/en/reference/index.rst
    a b usage of Sage. The examples are all test 
    1414Sage, and should produce exactly the same output as in this manual,
    1515except for line breaks.
    1616
    17 The Sage command line is briefly described in `The Sage Command Line
    18 <cmd/index.html>`_, which lists the command line options. For more
     17The Sage command line is briefly described in :doc:`The Sage Command Line
     18<cmd/index>`, which lists the command line options. For more
    1919details about the command line, see the Sage tutorial.
    2020
    21 The Sage graphical user interface is described in `The Sage Notebook
    22 <notebook/index.html>`_. This graphical user interface is unusual in
     21The Sage graphical user interface is described in :doc:`The Sage Notebook
     22<notebook/index>`. This graphical user interface is unusual in
    2323that it operates via your web browser. It provides you with Sage
    2424worksheets that you can edit and evaluate, which contain scalable
    2525typeset mathematics and beautiful antialiased images.
    Enjoy Sage! 
    3434Table of Contents
    3535=================
    3636
    37    * `The Sage Command Line <cmd/index.html>`_
    38    * `The Sage Notebook <notebook/index.html>`_
    39  
     37* :doc:`The Sage Command Line <cmd/index>`
     38* :doc:`The Sage Notebook <notebook/index>`
     39
    4040Calculus, Plotting
    4141------------------
    42  
    43    * `Symbolic Calculus <calculus/index.html>`_
    44    * `Constants <constants/index.html>`_
    45    * `Functions <functions/index.html>`_
    46    * `2D Graphics <plotting/index.html>`_
    47    * `3D Graphics <plot3d/index.html>`_
    48  
     42
     43* :doc:`Symbolic Calculus <calculus/index>`
     44* :doc:`Constants <constants/index>`
     45* :doc:`Functions <functions/index>`
     46* :doc:`2D Graphics <plotting/index>`
     47* :doc:`3D Graphics <plot3d/index>`
     48
    4949Combinatorics, Discrete Mathematics
    5050-----------------------------------
    51  
    52    * `Combinatorics <combinat/index.html>`_
    53    * `Graph Theory <graphs/index.html>`_
    54  
     51
     52* :doc:`Combinatorics <combinat/index>`
     53* :doc:`Graph Theory <graphs/index>`
     54
    5555Structures, Coercion, Categories
    5656--------------------------------
    5757
    58    * `Basic Structures <structure/index.html>`_
    59    * `Coercion <coercion/index.html>`_
    60    * `Category Theory and Categories <categories/index.html>`_
     58* :doc:`Basic Structures <structure/index>`
     59* :doc:`Coercion <coercion/index>`
     60* :doc:`Category Theory and Categories <categories/index>`
    6161
    6262Rings, Fields, Algebras
    6363-----------------------
    6464
    65    * `General Rings, Ideals, and Morphisms <rings/index.html>`_
    66    * `Standard Commutative Rings <rings_standard/index.html>`_
    67    * `Fixed and Arbitrary Precision Numerical Fields <rings_numerical/index.html>`_
    68    * `Algebraic Number Fields <number_fields/index.html>`_
    69    * `Function Fields <function_fields/index.html>`_
    70    * `p-Adics <padics/index.html>`_
    71    * `Polynomial Rings <polynomial_rings/index.html>`_
    72    * `Power Series Rings <power_series/index.html>`_
    73    * `Standard Semirings <semirings/index.html>`_
    74    * `Algebras <algebras/index.html>`_
    75    * `Quaternion Algebras <quat_algebras/index.html>`_
     65* :doc:`General Rings, Ideals, and Morphisms <rings/index>`
     66* :doc:`Standard Commutative Rings <rings_standard/index>`
     67* :doc:`Fixed and Arbitrary Precision Numerical Fields <rings_numerical/index>`
     68* :doc:`Algebraic Number Fields <number_fields/index>`
     69* :doc:`Function Fields <function_fields/index>`
     70* :doc:`p-Adics <padics/index>`
     71* :doc:`Polynomial Rings <polynomial_rings/index>`
     72* :doc:`Power Series Rings <power_series/index>`
     73* :doc:`Standard Semirings <semirings/index>`
     74* :doc:`Algebras <algebras/index>`
     75* :doc:`Quaternion Algebras <quat_algebras/index>`
    7676
    7777Groups, Monoids, Matrices, Modules
    7878----------------------------------
    7979
    80    * `Groups <groups/index.html>`_
    81    * `Monoids <monoids/index.html>`_
    82    * `Matrices and Spaces of Matrices <matrices/index.html>`_
    83    * `Modules <modules/index.html>`_
     80* :doc:`Groups <groups/index>`
     81* :doc:`Monoids <monoids/index>`
     82* :doc:`Matrices and Spaces of Matrices <matrices/index>`
     83* :doc:`Modules <modules/index>`
    8484
    8585Geometry and Topology
    8686---------------------
    8787
    88    * `Combinatorial Geometry <geometry/index.html>`_
    89    * `Cell Complexes and their Homology <homology/index.html>`_
    90    * `Differential Forms <tensor/index.html>`_
     88* :doc:`Combinatorial Geometry <geometry/index>`
     89* :doc:`Cell Complexes and their Homology <homology/index>`
     90* :doc:`Differential Forms <tensor/index>`
    9191
    9292Number Theory, Algebraic Geometry
    9393---------------------------------
    9494
    95    * `Quadratic Forms <quadratic_forms/index.html>`_
    96    * `L-Functions <lfunctions/index.html>`_
    97    * `Schemes <schemes/index.html>`_
    98    * `Elliptic, Plane, and Hyperelliptic Curves <plane_curves/index.html>`_
    99    * `Arithmetic Subgroups of SL_2(Z) <arithgroup/index.html>`_
    100    * `General Hecke Algebras and Hecke Modules <hecke/index.html>`_
    101    * `Modular Symbols <modsym/index.html>`_
    102    * `Modular Forms <modfrm/index.html>`_
    103    * `Modular Abelian Varieties <modabvar/index.html>`_
    104    * `Miscellaneous Modular-Form-Related Modules <modmisc/index.html>`_
     95* :doc:`Quadratic Forms <quadratic_forms/index>`
     96* :doc:`L-Functions <lfunctions/index>`
     97* :doc:`Schemes <schemes/index>`
     98* :doc:`Elliptic, Plane, and Hyperelliptic Curves <plane_curves/index>`
     99* :doc:`Arithmetic Subgroups of SL_2(Z) <arithgroup/index>`
     100* :doc:`General Hecke Algebras and Hecke Modules <hecke/index>`
     101* :doc:`Modular Symbols <modsym/index>`
     102* :doc:`Modular Forms <modfrm/index>`
     103* :doc:`Modular Abelian Varieties <modabvar/index>`
     104* :doc:`Miscellaneous Modular-Form-Related Modules <modmisc/index>`
    105105
    106106Miscellaneous Mathematics
    107107-------------------------
    108108
    109    * `Games <games/index.html>`_
    110    * `Symbolic Logic <logic/index.html>`_
    111    * `Cryptography <cryptography/index.html>`_
    112    * `Numerical Optimization <numerical/index.html>`_
    113    * `Probability <probability/index.html>`_
    114    * `Statistics <stats/index.html>`_
    115    * `Quantitative Finance <finance/index.html>`_
    116    * `Coding Theory <coding/index.html>`_
     109* :doc:`Games <games/index>`
     110* :doc:`Symbolic Logic <logic/index>`
     111* :doc:`Cryptography <cryptography/index>`
     112* :doc:`Numerical Optimization <numerical/index>`
     113* :doc:`Probability <probability/index>`
     114* :doc:`Statistics <stats/index>`
     115* :doc:`Quantitative Finance <finance/index>`
     116* :doc:`Coding Theory <coding/index>`
    117117
    118118Interfaces, Databases, Miscellany
    119119---------------------------------
    120120
    121    * `Interpreter Interfaces <interfaces/index.html>`_
    122    * `C/C++ Library Interfaces <libs/index.html>`_
    123    * `Databases <databases/index.html>`_
    124    * `Parallel Computing <parallel/index.html>`_
    125    * `Miscellaneous <misc/index.html>`_
     121* :doc:`Interpreter Interfaces <interfaces/index>`
     122* :doc:`C/C++ Library Interfaces <libs/index>`
     123* :doc:`Databases <databases/index>`
     124* :doc:`Parallel Computing <parallel/index>`
     125* :doc:`Miscellaneous <misc/index>`
    126126
    127127Other
    128128-----
    129129
    130    * `Sage's To Do List <todolist/index.html>`_
    131    * `History and License <history_and_license/index.html>`_
     130.. toctree::
     131   :maxdepth: 2
    132132
    133 .. include:: footer.txt
     133   todolist
     134
     135* :doc:`History and License <history_and_license/index>`
     136
     137Indices and Tables
     138------------------
     139
     140* :ref:`genindex`
     141* :ref:`modindex`
     142* :ref:`search`
  • new file doc/en/reference/todolist.rst

    diff --git a/doc/en/reference/todolist.rst b/doc/en/reference/todolist.rst
    new file mode 100644
    - +  
     1SAGE's To Do list
     2=================
     3
     4There is still some work to do :-) :
     5
     6.. warning::
     7
     8    This list is currently very incomplete as most doctests do not use the
     9    ``.. todo::`` markup.
     10
     11    .. todo::
     12
     13        Rewrite the hand-written TODOs by using the correct ``.. todo::``
     14        markup.
     15
     16The combined to do list is only available in the html version of the reference manual.
     17
     18.. todolist::
  • deleted file doc/en/reference/todolist/conf.py

    diff --git a/doc/en/reference/todolist/conf.py b/doc/en/reference/todolist/conf.py
    deleted file mode 100644
    + -  
    1 # -*- coding: utf-8 -*-
    2 # This file is execfile()d with the current directory set to its
    3 # containing dir.
    4 #
    5 # The contents of this file are pickled, so don't put values in the
    6 # namespace that aren't pickleable (module imports are okay, they're
    7 # removed automatically).
    8 #
    9 # All configuration values have a default; values that are commented
    10 # out serve to show the default.
    11 
    12 # See the parent directory's conf_sub module for details.
    13 import sys
    14 sys.path.append('..')
    15 from conf_sub import *
  • deleted file doc/en/reference/todolist/index.rst

    diff --git a/doc/en/reference/todolist/index.rst b/doc/en/reference/todolist/index.rst
    deleted file mode 100644
    + -  
    1 SAGE's To Do list
    2 =================
    3 
    4 There is still some work to do :-) :
    5 
    6 .. warning::
    7 
    8     This list is currently very incomplete as most doctests do not use the
    9     ``.. todo::`` markup.
    10 
    11     .. todo::
    12 
    13         Rewrite the hand-written TODOs by using the correct ``.. todo::``
    14         markup.
    15 
    16 The combined to do list is only available in the html version of the reference manual.
    17 
    18 .. todolist::