Ticket #5653: trac_5653_pretty_docstrings.patch

File trac_5653_pretty_docstrings.patch, 89.3 KB (added by mpatel, 12 years ago)

Conform to docbuild setup. This patch should be cumulative, against 3.4.2.

  • new file doc/introspect/__init__.py

    # HG changeset patch
    # User John H. Palmieri <palmieri@math.washington.edu>
    # Date 1240338630 25200
    # Node ID 3d7fce9264e936d6978bc1bc3f199b55fea431cd
    # Parent  7f9164053b2a6e9302193d8a3c710b826c6041cf
    pretty docstrings in notebook
    
    diff --git a/doc/introspect/__init__.py b/doc/introspect/__init__.py
    new file mode 100644
    - +  
     1 
  • new file doc/introspect/builder.py

    diff --git a/doc/introspect/builder.py b/doc/introspect/builder.py
    new file mode 100644
    - +  
     1#!/usr/bin/env python
     2import os, sys, subprocess, shutil, glob, optparse
     3
     4#We remove the current directory from sys.path right away
     5#so that we import sage from the proper spot
     6try:
     7    sys.path.remove(os.path.realpath(os.getcwd()))
     8except:
     9    pass
     10
     11from sage.misc.cachefunc import cached_method
     12
     13##########################################
     14#                Options                 #
     15##########################################
     16SAGE_DOC = os.environ['SAGE_DOC']
     17LANGUAGES = ['en', 'fr']
     18SPHINXOPTS  = ""
     19PAPER       = ""
     20
     21if PAPER == "a4":
     22    PAPEROPTS = "-D latex_paper_size=a4"
     23elif PAPER == "letter":
     24    PAPEROPTS = "-D latex_paper_size=letter"
     25else:
     26    PAPEROPTS = ""
     27
     28#Note that this needs to have the doctrees dir   
     29ALLSPHINXOPTS   = SPHINXOPTS + " " + PAPEROPTS + " . "
     30
     31
     32##########################################
     33#          Utility Functions             #
     34##########################################
     35def mkdir(path):
     36    """
     37    Makes the directory at path if it doesn't exist and returns the
     38    string path.
     39
     40    EXAMPLES::
     41
     42        sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
     43        sage: d = tmp_filename(); d
     44        '/.../tmp_...'
     45        sage: os.path.exists(d)
     46        False
     47        sage: dd = builder.mkdir(d)
     48        sage: d == dd
     49        True
     50        sage: os.path.exists(d)
     51        True
     52    """
     53    if not os.path.exists(path):
     54        os.makedirs(path)
     55    return path
     56
     57def copytree(src, dst, symlinks=False, ignore_errors=False):
     58    """
     59    Recursively copy a directory tree using copy2().
     60
     61    The destination directory must not already exist.
     62    If exception(s) occur, an Error is raised with a list of reasons.
     63
     64    If the optional symlinks flag is true, symbolic links in the
     65    source tree result in symbolic links in the destination tree; if
     66    it is false, the contents of the files pointed to by symbolic
     67    links are copied.
     68
     69    XXX Consider this example code rather than the ultimate tool.
     70
     71    """
     72    names = os.listdir(src)
     73    mkdir(dst)
     74    errors = []
     75    for name in names:
     76        srcname = os.path.join(src, name)
     77        dstname = os.path.join(dst, name)
     78        try:
     79            if symlinks and os.path.islink(srcname):
     80                linkto = os.readlink(srcname)
     81                os.symlink(linkto, dstname)
     82            elif os.path.isdir(srcname):
     83                copytree(srcname, dstname, symlinks)
     84            else:
     85                shutil.copy2(srcname, dstname)
     86            # XXX What about devices, sockets etc.?
     87        except (IOError, os.error), why:
     88            errors.append((srcname, dstname, str(why)))
     89        # catch the Error from the recursive copytree so that we can
     90        # continue with other files
     91        except shutil.Error, err:
     92            errors.extend(err.args[0])
     93    try:
     94        shutil.copystat(src, dst)
     95    except OSError, why:
     96        errors.extend((src, dst, str(why)))
     97    if errors and not ignore_errors:
     98        raise shutil.Error, errors
     99
     100
     101
     102##########################################
     103#             Builders                   #
     104##########################################
     105def builder_helper(type):
     106    """
     107    Returns a function which builds the documentation for
     108    output type type.
     109    """
     110    def f(self):
     111        output_dir = self._output_dir(type)
     112        os.chdir(self.dir)
     113
     114        build_command = 'sphinx-build'
     115        build_command += ' -b %s -d %s %s %s'%(type, self._doctrees_dir(),
     116                                               ALLSPHINXOPTS, output_dir)
     117        print build_command
     118        subprocess.call(build_command, shell=True)
     119
     120        print "Build finished.  The built documents can be found in %s"%output_dir
     121       
     122    f.is_output_format = True
     123    return f
     124       
     125
     126class DocBuilder(object):
     127    def __init__(self, name, lang='en'):
     128        """
     129        INPUT:
     130           
     131        - ``name`` - the name of a subdirectory in SAGE_DOC, such as
     132          'tutorial' or 'bordeaux_2008'
     133
     134        - ``lang`` - (default "en") the language of the document.
     135        """
     136        if '/' in name:
     137            lang, name = name.split(os.path.sep)
     138        self.name = name
     139        self.lang = lang
     140        self.dir = os.path.join(SAGE_DOC, lang, name)
     141
     142        #Make sure the .static and .templates directories are there
     143        mkdir(os.path.join(self.dir, "static"))
     144        mkdir(os.path.join(self.dir, "templates"))
     145
     146    def _output_dir(self, type):
     147        """
     148        Returns the directory where the output of type type is stored.
     149        If the directory does not exist, then it will automatically be
     150        created.
     151
     152        EXAMPLES::
     153
     154            sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
     155            sage: b = builder.DocBuilder('tutorial')
     156            sage: b._output_dir('html')
     157            '.../devel/sage/doc/output/html/en/tutorial'
     158        """
     159        return mkdir(os.path.join(SAGE_DOC, "output", type, self.lang, self.name))
     160
     161    def _doctrees_dir(self):
     162        """
     163        Returns the directory where the doctrees are stored.  If the
     164        directory does not exist, then it will automatically be
     165        created.
     166
     167        EXAMPLES::
     168
     169            sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
     170            sage: b = builder.DocBuilder('tutorial')
     171            sage: b._doctrees_dir()
     172            '.../devel/sage/doc/output/doctrees/en/tutorial'
     173        """
     174        return mkdir(os.path.join(SAGE_DOC, "output", 'doctrees', self.lang, self.name))
     175
     176    def _output_formats(self):
     177        """
     178        Returns a list of the possible output formats.
     179
     180        EXAMPLES::
     181
     182            sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
     183            sage: b = builder.DocBuilder('tutorial')
     184            sage: b._output_formats()
     185            ['changes', 'html', 'htmlhelp', 'json', 'latex', 'linkcheck', 'pickle', 'web']
     186
     187        """
     188        #Go through all the attributes of self and check to
     189        #see which ones have an 'is_output_format' attribute.  These
     190        #are the ones created with builder_helper.
     191        output_formats = []
     192        for attr in dir(self):
     193            if hasattr(getattr(self, attr), 'is_output_format'):
     194                output_formats.append(attr)
     195        output_formats.sort()
     196        return output_formats
     197
     198    def pdf(self):
     199        """
     200        Builds the PDF files for this document.  This is done by first
     201        (re)-building the LaTeX output, going into that LaTeX
     202        directory, and running 'make all-pdf' there.
     203
     204        EXAMPLES::
     205
     206            sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
     207            sage: b = builder.DocBuilder('tutorial')
     208            sage: b.pdf() #not tested
     209        """
     210        self.latex()
     211        os.chdir(self._output_dir('latex'))
     212        subprocess.call('make all-pdf', shell=True)
     213
     214        pdf_dir = self._output_dir('pdf')
     215        for pdf_file in glob.glob('*.pdf'):
     216            shutil.move(pdf_file, os.path.join(pdf_dir, pdf_file))
     217
     218        print "Build finished.  The built documents can be found in %s"%pdf_dir             
     219
     220    def clean(self, *args):
     221        """
     222        """
     223        import shutil
     224        shutil.rmtree(self._doctrees_dir())
     225        output_formats = list(args) if args else self._output_formats()
     226        for format in output_formats:
     227            shutil.rmtree(self._output_dir(format), ignore_errors=True)
     228       
     229    html = builder_helper('html')
     230    pickle = builder_helper('pickle')
     231    web = pickle
     232    json = builder_helper('json')                       
     233    htmlhelp = builder_helper('htmlhelp')
     234    latex = builder_helper('latex')
     235    changes = builder_helper('changes')
     236    linkcheck = builder_helper('linkcheck')
     237
     238class AllBuilder(object):
     239    """
     240    A class used to build all of the documentation.
     241    """
     242    def __getattr__(self, attr):
     243        """
     244        For any attributes not explicitly defined, we just go through
     245        all of the documents and call their attr.  For example,
     246        'AllBuilder().json()' will go through all of the documents
     247        and call the json() method on their builders.
     248        """
     249        from functools import partial
     250        return partial(self._wrapper, attr)
     251
     252    def _wrapper(self, name, *args, **kwds):
     253        """
     254        This is the function which goes through all of the documents
     255        and does the actual building.
     256        """
     257        for document in self.get_all_documents():
     258            getattr(get_builder(document), name)(*args, **kwds)
     259
     260    def get_all_documents(self):
     261        """
     262        Returns a list of all of the documents. A document is a directory within one of
     263        the language subdirectories of SAGE_DOC specified by the global LANGUAGES
     264        variable.
     265
     266        EXAMPLES::
     267
     268            sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
     269            sage: documents = builder.AllBuilder().get_all_documents()
     270            sage: 'en/tutorial' in documents
     271            True
     272        """
     273        documents = []
     274        for lang in LANGUAGES:
     275            for document in os.listdir(os.path.join(SAGE_DOC, lang)):
     276                documents.append(os.path.join(lang, document))
     277        return documents
     278
     279class WebsiteBuilder(DocBuilder):
     280    def html(self):
     281        """
     282        After we've finished building the website index page, we copy
     283        everything one directory up.
     284        """
     285        DocBuilder.html(self)
     286        html_output_dir = self._output_dir('html')
     287        copytree(html_output_dir,
     288                 os.path.realpath(os.path.join(html_output_dir, '..')),
     289                 ignore_errors=False)
     290
     291    def clean(self):
     292        """
     293        When we clean the output for the website index, we need to
     294        remove all of the HTML that were placed in the parent
     295        directory.
     296        """
     297        html_output_dir = self._output_dir('html')
     298        parent_dir = os.path.realpath(os.path.join(html_output_dir, '..'))
     299        for filename in os.listdir(html_output_dir):
     300            parent_filename = os.path.join(parent_dir, filename)
     301            if not os.path.exists(parent_filename):
     302                continue
     303            if os.path.isdir(parent_filename):
     304                shutil.rmtree(parent_filename, ignore_errors=True)
     305            else:
     306                os.unlink(parent_filename)
     307
     308        DocBuilder.clean(self)
     309
     310class ReferenceBuilder(DocBuilder):
     311    """
     312    This the class used to build the reference manual.  It is
     313    resposible for making sure the auto generated ReST files for the
     314    Sage library are up to date.
     315
     316    When building any output, we must first go through and check
     317    to see if we need to update any of the autogenerated ReST
     318    files.  There are two cases where this would happen:
     319
     320    1. A new module gets added to one of the toctrees.
     321   
     322    2. The actual module gets updated and possibly contains a new
     323       title.
     324    """
     325    def __init__(self, *args, **kwds):
     326        DocBuilder.__init__(self, *args, **kwds)
     327        self._wrap_builder_helpers()
     328
     329    def _wrap_builder_helpers(self):
     330        from functools import partial, update_wrapper
     331        for attr in dir(self):
     332            if hasattr(getattr(self, attr), 'is_output_format'):
     333                f = partial(self._wrapper, attr)
     334                f.is_output_format = True
     335                update_wrapper(f, getattr(self, attr))
     336                setattr(self, attr, f)
     337   
     338    def _wrapper(self, build_type, *args, **kwds):
     339        """
     340        This is the wrapper around the builder_helper methods that
     341        goes through and makes sure things are up to date.
     342        """
     343        #Write the .rst files for newly included modules
     344        for module_name in self.get_newly_included_modules(save=True):
     345            self.write_auto_rest_file(module_name)
     346
     347        #Update the .rst files for modified Python modules
     348        for module_name in self.get_modified_modules():
     349            self.write_auto_rest_file(module_name.replace(os.path.sep, '.'))
     350
     351        #Copy over the custom .rst files from _sage
     352        _sage = os.path.join(self.dir, '_sage')
     353        if os.path.exists(_sage):
     354            copytree(_sage, os.path.join(self.dir, 'sage'))
     355               
     356        getattr(DocBuilder, build_type)(self, *args, **kwds)
     357   
     358    def cache_filename(self):
     359        """
     360        Returns the filename where the pickle of the dictionary of
     361        already generated .rst files is stored.
     362        """
     363        return os.path.join(self._doctrees_dir(), 'reference.pickle')
     364
     365    @cached_method
     366    def get_cache(self):
     367        """
     368        Retreive the cache of already generated .rst files.  If it
     369        doesn't exist, then we just return an empty dictionary.
     370        """
     371        filename = self.cache_filename()
     372        if not os.path.exists(filename):
     373            return {}
     374
     375        import cPickle
     376        file = open(self.cache_filename(), 'rb')
     377        cache = cPickle.load(file)
     378        file.close()
     379        return cache
     380       
     381
     382    def save_cache(self):
     383        """
     384        Save the cache of already generated .rst files.
     385        """
     386        import cPickle
     387        file = open(self.cache_filename(), 'wb')
     388        cPickle.dump(self.get_cache(), file)
     389        file.close()
     390
     391    def get_sphinx_environment(self):
     392        """
     393        Returns the Sphinx environment for this project.
     394        """
     395        from sphinx.environment import BuildEnvironment
     396        class Foo(object):
     397            pass
     398        config = Foo()
     399        config.values = []
     400
     401        env_pickle = os.path.join(self._doctrees_dir(), 'environment.pickle')
     402        try:
     403            return BuildEnvironment.frompickle(config, env_pickle)
     404        except IOError:
     405            pass
     406                                           
     407    def get_modified_modules(self):
     408        """
     409        Returns an iterator for all the modules that have been modified
     410        since the docuementation was last built.
     411        """
     412        env = self.get_sphinx_environment()
     413        if env is None:
     414            return
     415        added, changed, removed = env.get_outdated_files(False)
     416        for name in changed:
     417            if name.startswith('sage'):
     418                yield name
     419
     420    def print_modified_modules(self):
     421        """
     422        Prints a list of all the modules that have been modified since
     423        the documentation was last built.
     424        """
     425        for module_name in self.get_modified_modules():
     426            print module_name
     427
     428    def get_all_rst_files(self, exclude_sage=True):
     429        """
     430        Returns an iterator for all rst files which are not
     431        autogenerated.
     432        """
     433        for directory, subdirs, files in os.walk(self.dir):
     434            if exclude_sage and directory.startswith(os.path.join(self.dir, 'sage')):
     435                continue
     436            for filename in files:
     437                if not filename.endswith('.rst'):
     438                    continue
     439                yield os.path.join(directory, filename)
     440
     441    def get_all_included_modules(self):
     442        """
     443        Returns an iterator for all modules which are included in the
     444        reference manual.
     445        """
     446        for filename in self.get_all_rst_files():
     447            for module in self.get_modules(filename):
     448                yield module
     449
     450    def get_newly_included_modules(self, save=False):
     451        """
     452        Returns an iterator for all modules that appear in the
     453        toctrees that don't appear in the cache.
     454        """
     455        cache = self.get_cache()
     456        new_modules = []
     457        for module in self.get_all_included_modules():
     458            if module not in cache:
     459                cache[module] = True
     460                yield module
     461        if save:
     462            self.save_cache()
     463
     464    def print_newly_included_modules(self):
     465        """
     466        Prints all of the modules that appear in the toctrees that
     467        don't appear in the cache.
     468        """
     469        for module_name in self.get_newly_included_modules():
     470            print module_name
     471
     472    def get_modules(self, filename):
     473        """
     474        Given a filename for a .rst file, return an iterator for
     475        all of the autogenerated rst files that it includes.
     476        """
     477        #Create the regular expression used to detect an autogenerated file
     478        import re
     479        auto_re = re.compile('^\s*(..\/)*(sage\/[\w\/]*)\s*$')
     480
     481        #Read the lines
     482        f = open(filename)
     483        lines = f.readlines()
     484        f.close()
     485
     486        for line in lines:
     487            match = auto_re.match(line)
     488            if match:
     489                yield match.group(2).replace(os.path.sep, '.')
     490               
     491    def get_module_docstring_title(self, module_name):
     492        """
     493        Returns the title of the module from its docstring.
     494        """
     495        #Try to import the module
     496        try:
     497            import sage.all
     498            __import__(module_name)
     499        except ImportError, err:
     500            raise
     501            print "Warning: could not import %s"%module_name
     502            print err
     503            return "UNABLE TO IMPORT MODULE"
     504        module = sys.modules[module_name]
     505
     506        #Get the docstring
     507        doc = module.__doc__
     508        if doc is None:
     509            doc = module.doc if hasattr(module, 'doc') else ""
     510
     511        #Extract the title
     512        i = doc.find('\n')
     513        if i != -1:
     514            return doc[i+1:].lstrip().splitlines()[0]
     515        else:
     516            return doc
     517
     518    def write_auto_rest_file(self, module_name):
     519        """
     520        Writes the autogenerated .rst file for module_name.
     521        """
     522        if not module_name.startswith('sage'):
     523            return
     524        filename = self.dir + os.path.sep + module_name.replace('.',os.path.sep) + '.rst'
     525        mkdir(os.path.dirname(filename))
     526       
     527        outfile = open(filename, 'w')
     528
     529        title = self.get_module_docstring_title(module_name)
     530
     531        if title == '':
     532            print "WARNING: Missing title for", module_name
     533            title = "MISSING TITLE"
     534
     535        outfile.write(title + '\n')
     536        outfile.write('='*len(title) + "\n\n")
     537        outfile.write('.. This file has been autogenerated.\n\n')
     538        automodule = '.. automodule:: %s\n   :members:\n   :undoc-members:\n\n'
     539        outfile.write(automodule%module_name)
     540
     541        outfile.close()
     542
     543    def clean_auto(self):
     544        """
     545        Remove the cache file for the autogenerated files as well as
     546        the files themselves.
     547        """
     548        if os.path.exists(self.cache_filename()):
     549            os.unlink(self.cache_filename())
     550
     551        import shutil
     552        shutil.rmtree(self.dir + '/sage')
     553
     554    def get_unincluded_modules(self):
     555        """
     556        Returns an iterator for all the modules in the Sage library
     557        which are not included in the reference manual.
     558        """
     559        #Make a dictionary of the included modules
     560        included_modules = {}
     561        for module_name in self.get_all_included_modules():
     562            included_modules[module_name] = True
     563       
     564        base_path = os.path.join(os.environ['SAGE_ROOT'], 'devel', 'sage', 'sage')
     565        for directory, subdirs, files in os.walk(base_path):
     566            for filename in files:
     567                if not (filename.endswith('.py') or
     568                        filename.endswith('.pyx')):
     569                    continue
     570               
     571                path = os.path.join(directory, filename)
     572
     573                #Create the module name
     574                module_name = path[len(base_path):].replace(os.path.sep, '.')
     575                module_name = 'sage' + module_name
     576                module_name = module_name[:-4] if module_name.endswith('pyx') else module_name[:-3]
     577
     578                #Exclude some ones  -- we don't want init the manual
     579                if module_name.endswith('__init__') or module_name.endswith('all'):
     580                    continue
     581
     582                if module_name not in included_modules:
     583                    yield module_name
     584               
     585    def print_unincluded_modules(self):
     586        """
     587        Prints all of the modules which are not included in the Sage
     588        reference manual.
     589        """
     590        for module_name in self.get_unincluded_modules():
     591            print module_name
     592
     593    def print_included_modules(self):
     594        """
     595        Prints all of the modules that are included in the Sage reference
     596        manual.
     597        """
     598        for module_name in self.get_all_included_modules():
     599            print module_name
     600
     601       
     602
     603def get_builder(name):
     604    """
     605    Returns a either a AllBuilder or DocBuilder object depending
     606    on whether ``name`` is 'all' or not.  These are the objects
     607    which do all the real work in building the documentation.
     608    """
     609    if name == 'all':
     610        return AllBuilder()
     611    elif name.endswith('reference'):
     612        return ReferenceBuilder(name)
     613    elif name.endswith('website'):
     614        return WebsiteBuilder(name)
     615    else:
     616        return DocBuilder(name)
     617             
     618
     619def help_message():
     620    """
     621    Returns the help message.
     622    """
     623    all_b = AllBuilder()
     624    docs = all_b.get_all_documents()
     625    docs = [(d[3:] if d[0:3] == 'en/' else d) for d in docs]
     626    tut_b = DocBuilder('en/tutorial')
     627    formats = tut_b._output_formats()
     628    formats.remove('html')
     629    help = "Usage: sage -docbuild {document} {format}\n"
     630    help += "Where {document} is one of:\n    "
     631    help += "\n    ".join(docs)
     632    help += "\nor 'all' for all documents, and {format} is one of:\n    "
     633    help += 'html, pdf, ' + ', '.join(formats)
     634    help += "\n"
     635    help += "When building the reference manual, there are several additional\n"
     636    help += "values for {format}:\n"
     637    help += "    print_modified_modules: list modules modified since the documentation\n"
     638    help += "         was last built\n"
     639    help += "    print_newly_included_modules: list modules added to the\n"
     640    help += "         documentation since it was last built\n"
     641    help += "    print_unincluded_modules: list modules not included in the documentation\n"
     642    help += "    print_included_modules: list modules included in the documentation\n"
     643    print help
     644
     645
     646parser = optparse.OptionParser(usage="usage: sage -docbuild [options] name type")
     647parser.add_option("--jsmath", action="store_true",
     648                  help="render math using jsMath")
     649parser.print_help = help_message
     650
     651if __name__ == '__main__':
     652    options, args = parser.parse_args()
     653
     654    if options.jsmath:
     655        os.environ['SAGE_DOC_JSMATH'] = "True"
     656
     657    #Get the name of the document we are trying to build
     658    try:
     659        name, type = args
     660    except ValueError:
     661        print "You must specify the document name and the output format"
     662        sys.exit(0)
     663   
     664    #Make sure common/static exists
     665    mkdir(os.path.join(SAGE_DOC, 'common', 'static'))
     666
     667    #Get the builder and build
     668    getattr(get_builder(name), type)()
  • new file doc/introspect/conf.py

    diff --git a/doc/introspect/conf.py b/doc/introspect/conf.py
    new file mode 100644
    - +  
     1import sys, os
     2SAGE_DOC = os.environ['SAGE_ROOT'] + '/devel/sage/doc'
     3
     4# If your extensions are in another directory, add it here. If the directory
     5# is relative to the documentation root, use os.path.abspath to make it
     6# absolute, like shown here.
     7#sys.path.append(os.path.abspath('.'))
     8
     9# General configuration
     10# ---------------------
     11
     12# Add any Sphinx extension module names here, as strings. They can be extensions
     13# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
     14extensions = ['sphinx.ext.autodoc', 'sphinx.ext.jsmath']
     15
     16jsmath_path = '/javascript_local/jsmath/easy/load.js'
     17
     18# Add any paths that contain templates here, relative to this directory.
     19templates_path = [SAGE_DOC + '/introspect/templates', 'templates']
     20
     21# The suffix of source filenames.
     22source_suffix = '.rst'
     23
     24# The master toctree document.
     25master_doc = 'index'
     26
     27# General information about the project.
     28project = u""
     29copyright = u'2008, The Sage Group'
     30
     31# The version info for the project you're documenting, acts as replacement for
     32# |version| and |release|, also used in various other places throughout the
     33# built documents.
     34#
     35# The short X.Y version.
     36# from sage.version import version
     37# release = version
     38
     39#version = '3.1.2'
     40# The full version, including alpha/beta/rc tags.
     41#release = '3.1.2'
     42
     43# The language for content autogenerated by Sphinx. Refer to documentation
     44# for a list of supported languages.
     45#language = None
     46
     47# There are two options for replacing |today|: either, you set today to some
     48# non-false value, then it is used:
     49#today = ''
     50# Else, today_fmt is used as the format for a strftime call.
     51#today_fmt = '%B %d, %Y'
     52
     53# List of documents that shouldn't be included in the build.
     54#unused_docs = []
     55
     56# List of directories, relative to source directory, that shouldn't be searched
     57# for source files.
     58exclude_trees = ['.build']
     59
     60# The reST default role (used for this markup: `text`) to use for all documents.
     61default_role = 'math'
     62
     63# If true, '()' will be appended to :func: etc. cross-reference text.
     64#add_function_parentheses = True
     65
     66# If true, the current module name will be prepended to all description
     67# unit titles (such as .. function::).
     68#add_module_names = True
     69
     70# If true, sectionauthor and moduleauthor directives will be shown in the
     71# output. They are ignored by default.
     72#show_authors = False
     73
     74# The name of the Pygments (syntax highlighting) style to use.
     75pygments_style = 'sphinx'
     76
     77
     78# Options for HTML output
     79# -----------------------
     80
     81# The style sheet to use for HTML and HTML Help pages. A file of that name
     82# must exist either in Sphinx' static/ path, or in one of the custom paths
     83# given in html_static_path.
     84html_style = 'default.css'
     85
     86# The name for this set of Sphinx documents.  If None, it defaults to
     87# "<project> v<release> documentation".
     88#html_title = None
     89
     90# A shorter title for the navigation bar.  Default is the same as html_title.
     91#html_short_title = None
     92
     93# The name of an image file (within the static path) to place at the top of
     94# the sidebar.
     95#html_logo = 'sagelogo-word.ico'
     96
     97# The name of an image file (within the static path) to use as favicon of the
     98# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
     99# pixels large.
     100# html_favicon = 'sageicon.png'
     101
     102# Add any paths that contain custom static files (such as style sheets) here,
     103# relative to this directory. They are copied after the builtin static files,
     104# so a file named "default.css" will overwrite the builtin "default.css".
     105html_static_path = [SAGE_DOC +'/introspect/static', 'static']
     106
     107# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
     108# using the given strftime format.
     109#html_last_updated_fmt = '%b %d, %Y'
     110
     111# If true, SmartyPants will be used to convert quotes and dashes to
     112# typographically correct entities.
     113#html_use_smartypants = True
     114
     115# Custom sidebar templates, maps document names to template names.
     116#html_sidebars = {}
     117
     118# Additional templates that should be rendered to pages, maps page names to
     119# template names.
     120#html_additional_pages = {}
     121
     122# If false, no module index is generated.
     123html_use_modindex = False
     124
     125# If false, no index is generated.
     126html_use_index = False
     127
     128# If true, the index is split into individual pages for each letter.
     129#html_split_index = True
     130
     131# If true, the reST sources are included in the HTML build as _sources/<name>.
     132html_copy_source = False
     133
     134# If true, an OpenSearch description file will be output, and all pages will
     135# contain a <link> tag referring to it.  The value of this option must be the
     136# base URL from which the finished HTML is served.
     137#html_use_opensearch = ''
     138
     139# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
     140#html_file_suffix = ''
     141
     142# Output file base name for HTML help builder.
     143#htmlhelp_basename = ''
     144
     145
     146# Options for LaTeX output
     147# ------------------------
     148
     149# The paper size ('letter' or 'a4').
     150#latex_paper_size = 'letter'
     151
     152# The font size ('10pt', '11pt' or '12pt').
     153#latex_font_size = '10pt'
     154
     155# Grouping the document tree into LaTeX files. List of tuples
     156# (source start file, target name, title, author, document class [howto/manual]).
     157#latex_documents = []
     158
     159# The name of an image file (relative to this directory) to place at the top of
     160# the title page.
     161#latex_logo = 'sagelogo-word.png'
     162
     163# For "manual" documents, if this is true, then toplevel headings are parts,
     164# not chapters.
     165#latex_use_parts = False
     166
     167# Additional stuff for the LaTeX preamble.
     168#latex_preamble = ''
     169#latex_preamble = '\usepackage{amsmath}\n\usepackage{amsfonts}\n'
     170
     171# Documents to append as an appendix to all manuals.
     172#latex_appendices = []
     173
     174# If false, no module index is generated.
     175#latex_use_modindex = True
     176
     177
     178#####################################################
     179
     180def process_docstring_aliases(app, what, name, obj, options, docstringlines):
     181    """
     182    Change the docstrings for aliases to point to the original object.
     183    """
     184    basename = name.rpartition('.')[2]
     185    if hasattr(obj, '__name__') and obj.__name__ != basename:
     186        docstringlines[:] = ['See :obj:`%s`.' % name]
     187
     188def process_docstring_cython(app, what, name, obj, options, docstringlines):
     189    """
     190    Remove Cython's filename and location embedding.
     191    """
     192    if len(docstringlines) <= 1:
     193        return
     194
     195    first_line = docstringlines[0]
     196    if first_line.startswith('File:') and '(starting at' in first_line:
     197        #Remove the first two lines
     198        docstringlines.pop(0)
     199        docstringlines.pop(0)
     200
     201def process_docstring_module_title(app, what, name, obj, options, docstringlines):
     202    """
     203    Removes the first line from the beginning of the module's docstring.  This
     204    corresponds to the title of the module's documentation page.
     205    """
     206    if what != "module":
     207        return
     208
     209    #Remove any additional blank lines at the beginning
     210    title_removed = False
     211    while len(docstringlines) > 1 and not title_removed:
     212        if docstringlines[0].strip() != "":
     213            title_removed = True
     214        docstringlines.pop(0)
     215
     216    #Remove any additional blank lines at the beginning
     217    while len(docstringlines) > 1:
     218        if docstringlines[0].strip() == "":
     219            docstringlines.pop(0)
     220        else:
     221            break
     222
     223       
     224def setup(app):
     225    app.connect('autodoc-process-docstring', process_docstring_cython)
     226    app.connect('autodoc-process-docstring', process_docstring_module_title)
  • new file doc/introspect/static/.empty

    diff --git a/doc/introspect/static/.empty b/doc/introspect/static/.empty
    new file mode 100644
    - +  
     1 
     2 No newline at end of file
  • new file doc/introspect/templates/layout.html

    diff --git a/doc/introspect/templates/layout.html b/doc/introspect/templates/layout.html
    new file mode 100644
    - +  
     1<div class="docstring">
     2    {% block body %} {% endblock %}
     3</div>
  • sage/misc/sagedoc.py

    diff --git a/sage/misc/sagedoc.py b/sage/misc/sagedoc.py
    a b  
    2020#*****************************************************************************
    2121
    2222import os
    23 #('\\item', '*'), \
    24 substitutes = [('\\_','_'),\
    25                ('\\item', '* '), \
    26                ('\\to', '-->'), \
    27                ('<BLANKLINE>',''), \
    28                ('\\leq', '<='), \
    29                ('\\geq', '>='), \
    30                ('\\le', '<='), \
    31                ('\\ge', '>='), \
    32                ('\\bf', ''),\
    33                ('\\sage', 'SAGE'), \
    34                ('\\SAGE', 'SAGE'), \
    35                ('\\rm', ''), \
    36                ('cdots', '...'), \
    37                ('\\cdot', ' *'), \
    38                ('$',''), ('\\',''), ('backslash','\\'), \
    39                ('begin{enumerate}',''), ('end{enumerate}',''), \
    40                ('begin{description}',''), ('end{description}',''), \
    41                ('begin{itemize}',''), ('end{itemize}',''), \
    42                ('begin{verbatim}',''), ('end{verbatim}',''), \
    43                ('mapsto', ' |--> '), \
    44                ('ldots', '...'), ('note{','NOTE: ')]
    45 
     23# two kinds of substitutions: math, which should only be done on the
     24# command line -- in the notebook, these should instead by taken care
     25# of by jsMath -- and nonmath, which should be done always.
     26math_substitutes = [('\\to', '-->'),
     27                    ('\\leq', '<='),
     28                    ('\\geq', '>='),
     29                    ('\\le', '<='),
     30                    ('\\ge', '>='),
     31                    ('cdots', '...'),
     32                    ('\\cdot', ' *'),
     33                    (' \\times', ' x'),
     34                    ('\\times', ' x'),
     35                    ('backslash','\\'),
     36                    ('mapsto', ' |--> '),
     37                    ('ldots', '...')]
     38nonmath_substitutes = [('\\_','_'),
     39                       ('\\item', '* '),
     40                       ('<BLANKLINE>',''),
     41                       ('\\bf', ''),
     42                       ('\\sage', 'SAGE'),
     43                       ('\\SAGE', 'SAGE'),
     44                       ('\\rm', ''),
     45                       ('backslash','\\'),
     46                       ('begin{enumerate}',''),
     47                       ('end{enumerate}',''),
     48                       ('begin{description}',''),
     49                       ('end{description}',''),
     50                       ('begin{itemize}',''),
     51                       ('end{itemize}',''),
     52                       ('begin{verbatim}',''),
     53                       ('end{verbatim}',''),
     54                       ('note{','NOTE: ')]
    4655
    4756def _rmcmd(s, cmd, left='', right=''):
    4857    """
     
    112121itempattern = re.compile(r"\\item\[?([^]]*)\]? *(.*)")
    113122itemreplace = r"* \1 \2"
    114123
    115 def detex(s):
     124def detex(s, embedded=False):
    116125    """nodetex
    117126    This strips LaTeX commands from a string; it is used by the
    118127    ``format`` function to process docstrings for display from the
    119128    command line interface.
    120129
    121     INPUT: ``s``, a string.
     130    INPUT:
     131
     132    - ``s`` - string
     133    - ``embedded`` - boolean (optional, default False)
     134
     135    If ``embedded`` is False, then do the replacements in both
     136    ``math_substitutes`` and ``nonmath_substitutes``.  If True, then
     137    only do ``nonmath_substitutes``.
    122138
    123139    OUTPUT: string
    124140
     
    129145        'Some math: `n >= k`.  A website: sagemath.org.'
    130146        sage: detex(r'More math: `x \mapsto y`.  {\bf Bold face}.')
    131147        'More math: `x  |-->  y`.  { Bold face}.'
    132         sage: detex(r'$a, b, c, \ldots, z$')
    133         'a, b, c, ..., z'
     148        sage: detex(r'`a, b, c, \ldots, z`')
     149        '`a, b, c, ..., z`'
     150        sage: detex(r'`a, b, c, \ldots, z`', embedded=True)
     151        '`a, b, c, \\\\ldots, z`'
    134152    """
    135153    s = _rmcmd(s, 'url')
    136154    s = _rmcmd(s, 'code')
     
    142160    s = _rmcmd(s, 'subsubsection')
    143161    s = _rmcmd(s, 'note', 'NOTE: ', '')
    144162    s = _rmcmd(s, 'emph', '*', '*')
     163    s = _rmcmd(s, 'textbf', '*', '*')
    145164
    146165    s = re.sub(itempattern, itemreplace, s)
    147    
    148     for a,b in substitutes:
     166
     167    if not embedded: # not in the notebook
     168        for a,b in math_substitutes:  # do math substitutions
     169            s = s.replace(a,b)
     170        s = s.replace('\\','')        # nuke backslashes
     171        s = s.replace('.. math::\n', '')  # get rid of .. math:: directives
     172    else:
     173        s = s.replace('\\','\\\\')    # double up backslashes for jsMath
     174    for a,b in nonmath_substitutes:
    149175        s = s.replace(a,b)
    150176    return s
    151177
    152 def format(s):
     178def format(s, embedded=False):
    153179    """
    154180    Format Sage documentation ``s`` for viewing with IPython.
    155181
     
    157183    text, and if ``s`` contains a string of the form "<<<obj>>>",
    158184    then it replaces it with the docstring for "obj".
    159185
    160     INPUT: ``s`` - string
     186    INPUT:
     187
     188    - ``s`` - string
     189    - ``embedded`` - boolean (optional, default False)
    161190
    162191    OUTPUT: string
    163192
     193    Set ``embedded`` equal to True if formatting for use in the
     194    notebook; this just gets passed as an argument to ``detex``.
     195
    164196    EXAMPLES::
    165197
    166198        sage: from sage.misc.sagedoc import format
     
    216248            t = 'Definition: ' + t0 + '\n\n' + t1
    217249            docs.add(obj)
    218250        s = s[:i] + '\n' + t + s[i+6+j:]
    219            
     251
    220252    if 'nodetex' not in directives:
    221         s = detex(s)
     253        s = detex(s, embedded=embedded)
    222254    return s
    223255
    224256def format_src(s):
  • sage/misc/sageinspect.py

    diff --git a/sage/misc/sageinspect.py b/sage/misc/sageinspect.py
    a b  
    114114
    115115import inspect
    116116import os
     117EMBEDDED_MODE = False
    117118
    118119def isclassinstance(obj):
    119120    r"""
     
    400401        if s[:4] == 'self':
    401402            s = s[4:]
    402403        s = s.lstrip(',').strip()
     404        # for use with typesetting the definition with the notebook:
     405        # sometimes s contains "*args" or "**keywds", and the
     406        # asterisks confuse ReST/sphinx/docutils, so escape them:
     407        # change * to \*, and change ** to \**.
     408        if EMBEDDED_MODE:
     409            s = s.replace('**', '\\**')  # replace ** with \**
     410            t = ''
     411            while True:  # replace * with \*
     412                i = s.find('*')
     413                if i == -1:
     414                    break
     415                elif i > 0 and s[i-1] == '\\':
     416                    if s[i+1] == "*":
     417                        t += s[:i+2]
     418                        s = s[i+2:]
     419                    else:
     420                        t += s[:i+1]
     421                        s = s[i+1:]
     422                    continue
     423                elif i > 0 and s[i-1] == '*':
     424                    t += s[:i+1]
     425                    s = s[i+1:]
     426                    continue
     427                else:
     428                    t += s[:i] + '\\*'
     429                    s = s[i+1:]
     430            s = t + s
    403431        return obj_name + '(' + s + ')'
    404432    except (AttributeError, TypeError, ValueError):
    405433        return '%s( [noargspec] )'%obj_name
     
    439467
    440468    if r is None:
    441469        return ''
    442     s = sage.misc.sagedoc.format(str(r))
     470
     471    s = sage.misc.sagedoc.format(str(r), embedded=EMBEDDED_MODE)
    443472
    444473    # If there is a Cython embedded position, it needs to be stripped
    445474    pos = _extract_embedded_position(s)
  • sage/server/notebook/cell.py

    diff --git a/sage/server/notebook/cell.py b/sage/server/notebook/cell.py
    a b  
    3434
    3535import os, shutil
    3636
    37 from   sage.misc.misc import word_wrap
     37from   sage.misc.misc import word_wrap, SAGE_ROOT
    3838from   sage.misc.html import math_parse
    3939from   sage.misc.preparser import strip_string_literals
    4040from   sage.misc.package   import is_package_installed
     
    4646else:
    4747    JEDITABLE_TINYMCE = False
    4848
     49# Introspection.  The cache directory is a module-scope variable set
     50# in the first call to Cell.set_introspect_html().
     51_SAGE_INTROSPECT = None
     52import errno, hashlib, time
     53from sphinx.application import Sphinx
     54
    4955
    5056class Cell_generic:
    5157    def is_interactive_cell(self):
     
    14311437    # Introspection #
    14321438    #################
    14331439    def set_introspect_html(self, html, completing=False):
    1434         if completing:
     1440        if html == "" or completing:
    14351441            self.__introspect_html = html
     1442        elif html.find("`") == -1 and html.find("::") == -1:
     1443            # html doesn't seem to be in ReST format so use docutils
     1444            # to process the preamble ("**File:**" etc.)  and put
     1445            # everything else in a <pre> block.
     1446            i = html.find("**Docstring:**")
     1447            if i != -1:
     1448                preamble = html[:i+14]
     1449                from docutils.core import publish_parts
     1450                preamble = publish_parts(html[:i+14], writer_name='html')['body']
     1451                html = html[i+14:]
     1452            else:
     1453                preamble = ""
     1454            self.__introspect_html = '<div class="docstring">' + preamble + '<pre>' + html + '</pre></div>'
    14361455        else:
    1437             html = escape(html).strip()
    1438             self.__introspect_html = '<pre class="introspection">'+html+'</pre>'
     1456            # html is in ReST format, so use Sphinx to process it
     1457           
     1458            # Set the location of the introspection cache, "permanent"
     1459            # or temporary.  The former, DOT_SAGE/sage_notebook/doc,
     1460            # can pool queries from multiple worksheet processes.  The
     1461            # latter is exclusive to a worksheet's process.  The Sage
     1462            # cleaner should delete the temporary directory (or
     1463            # directories) after the notebook server exits.
     1464            global _SAGE_INTROSPECT
     1465            if _SAGE_INTROSPECT is None:
     1466                from sage.misc.misc import DOT_SAGE, tmp_dir
     1467                # It's important to use os.path.join, instead of +,
     1468                # because Sphinx counts on normalized paths.  It's also
     1469                # more portable.
     1470                std_doc_dir = os.path.join(DOT_SAGE, 'sage_notebook/doc')
     1471                try:
     1472                    os.makedirs(std_doc_dir)
     1473                    _SAGE_INTROSPECT = std_doc_dir
     1474                except OSError, error:
     1475                    if error.errno == errno.EEXIST:
     1476                        if os.access(std_doc_dir, os.R_OK | os.W_OK | os.X_OK):
     1477                            _SAGE_INTROSPECT = std_doc_dir
     1478                        else:
     1479                            _SAGE_INTROSPECT = tmp_dir()
     1480                    else:
     1481                        _SAGE_INTROSPECT = tmp_dir()
     1482                print 'Introspection cache: ', _SAGE_INTROSPECT
     1483                       
     1484            # We get a quick checksum of the input.  MD5 admits
     1485            # collisions, but we're not concerned about such security
     1486            # issues here.  Of course, if performance permits, we can
     1487            # choose a more robust hash function.
     1488            hash = hashlib.md5(html).hexdigest()
     1489            base_name = os.path.join(_SAGE_INTROSPECT, hash)
     1490            html_name = base_name + '.html'
     1491
     1492            # Multiple processes might try to read/write the target
     1493            # HTML file simultaneously.  We use a file-based lock.
     1494            # Since we care only about the target's contents, and
     1495            # we've configured Sphinx accordingly, we allow multiple
     1496            # simultaneous instances of Sphinx, as long as their
     1497            # targets are different.  Systems which don't properly
     1498            # implement os.O_EXCL may require coarser locking.
     1499
     1500            # The Pythonic cross-platform file lock below is adapted
     1501            # from
     1502            # http://www.evanfosmark.com/2009/01/cross-platform-file-locking-support-in-python/
     1503            lock_name = base_name + '.lock'
     1504
     1505            # Try to acquire the lock, periodically.  If we time out,
     1506            # we fall back to plainly formatted documentation.
     1507            timeout = 0.5
     1508            delay = 0.05
     1509            start_time = time.time()
     1510
     1511            while True:
     1512                try:
     1513                    # This operation is atomic on platforms which
     1514                    # properly implement os.O_EXCL:
     1515                    fd_lock = os.open(lock_name, os.O_CREAT | os.O_EXCL | os.O_RDWR)
     1516                    break;
     1517                except OSError, err:
     1518                    if (err.errno != errno.EEXIST) or (time.time() - start_time >= timeout):
     1519                        plain_html = escape(html).strip()
     1520                        self.__introspect_html = '<pre class="introspection">' + plain_html + '</pre>'
     1521                        return
     1522                    time.sleep(delay)
     1523
     1524            # We've acquired the lock.  Use cached HTML or run Sphinx.
     1525            try:
     1526                open(html_name, 'r')
     1527                print 'Found: %s' % html_name
     1528            except IOError:
     1529                html = html.replace('\\\\', '\\')
     1530                rst_name = base_name + '.rst'
     1531                fd_rst = open(rst_name, 'w')
     1532                fd_rst.write(html)
     1533                fd_rst.close()
     1534
     1535                # Sphinx setup.  The constructor is Sphinx(srcdir,
     1536                # confdir, outdir, doctreedir, buildername,
     1537                # confoverrides, status, warning, freshenv).
     1538                srcdir = os.path.normpath(_SAGE_INTROSPECT)
     1539
     1540                # Note: It's crucial that confdir* contains a
     1541                # customized conf.py and layout.html.  In particular,
     1542                # we've disabled index generation and told Sphinx to
     1543                # output almost exactly the HTML we display.  Sphinx
     1544                # also pickles its environment in doctreedir, but we
     1545                # force Sphinx never to load this pickle with
     1546                # freshenv=True.
     1547                confdir = os.path.join(SAGE_ROOT, 'devel/sage/doc/introspect')
     1548                doctreedir = os.path.normpath(base_name)
     1549                confoverrides = {'html_context' : {}, 'master_doc' : hash}
     1550
     1551                # To suppress output, use this:
     1552#                sphinx_app = Sphinx(srcdir, confdir, srcdir, doctreedir, 'html', confoverrides, None, None, True)
     1553
     1554                # For verbose output, use these instead:
     1555                import sys
     1556                sphinx_app = Sphinx(srcdir, confdir, srcdir, doctreedir, 'html', confoverrides, sys.stdout, sys.stderr, True)
     1557
     1558                # Run Sphinx. The first argument corresponds to
     1559                # sphinx-build's "write all files" -a flag, which we
     1560                # set to None.
     1561                sphinx_app.build(None, [rst_name])
     1562
     1563                # We delete .rst files, so future Sphinx runs don't
     1564                # keep track of them.  We also delete doctrees.
     1565                try:
     1566                    os.unlink(rst_name)
     1567                except OSError:
     1568                    pass
     1569                try:
     1570                    shutil.rmtree(doctreedir)
     1571                    os.unlink(doctreedir)
     1572                except OSError:
     1573                    pass
     1574
     1575                print 'Built: %s' % html_name
     1576            finally:
     1577                # Contents should be flushed on close().
     1578                fd_html = open(html_name, 'r')
     1579                new_html = fd_html.read()
     1580                fd_html.close()
     1581
     1582                # We release the lock and delete the lock file.
     1583                os.close(fd_lock)
     1584                os.unlink(lock_name)
     1585
     1586                new_html = new_html.replace('<pre>', '<pre class="literal-block">')
     1587                self.__introspect_html = new_html
     1588                return
    14391589
    14401590    def introspect_html(self):
    14411591        if not self.introspect():
  • sage/server/notebook/css.py

    diff --git a/sage/server/notebook/css.py b/sage/server/notebook/css.py
    a b  
    293293div.introspection {
    294294}
    295295
     296div.docstring {
     297  font-family:arial;
     298  background-color: #f1f1f1;
     299  color: blue;
     300  border: solid 1px black;
     301  padding:8px;
     302  margin:8px;
     303}
     304
     305pre.literal-block {
     306  background-color: #efc;
     307  color: blue;   
     308}
     309
    296310pre.introspection {
    297311  font-family: monospace;
    298312  font-size:15px;
    299   background-color: #efefef;
     313  background-color: #f1f1f1;
     314  color: blue;
    300315  border: solid 1px black;
    301316  padding:8px;
    302317  margin:8px;
     
    16351650   background-color: #990000;   
    16361651}
    16371652
     1653
     1654
     1655.hll { background-color: #ffffcc }
     1656.c { color: #408090; font-style: italic } /* Comment */
     1657.err { border: 1px solid #FF0000 } /* Error */
     1658.k { color: #007020; font-weight: bold } /* Keyword */
     1659.o { color: #666666 } /* Operator */
     1660.cm { color: #408090; font-style: italic } /* Comment.Multiline */
     1661.cp { color: #007020 } /* Comment.Preproc */
     1662.c1 { color: #408090; font-style: italic } /* Comment.Single */
     1663.cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
     1664.gd { color: #A00000 } /* Generic.Deleted */
     1665.ge { font-style: italic } /* Generic.Emph */
     1666.gr { color: #FF0000 } /* Generic.Error */
     1667.gh { color: #000080; font-weight: bold } /* Generic.Heading */
     1668.gi { color: #00A000 } /* Generic.Inserted */
     1669.go { color: #303030 } /* Generic.Output */
     1670.gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
     1671.gs { font-weight: bold } /* Generic.Strong */
     1672.gu { color: #800080; font-weight: bold } /* Generic.Subheading */
     1673.gt { color: #0040D0 } /* Generic.Traceback */
     1674.kc { color: #007020; font-weight: bold } /* Keyword.Constant */
     1675.kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
     1676.kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
     1677.kp { color: #007020 } /* Keyword.Pseudo */
     1678.kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
     1679.kt { color: #902000 } /* Keyword.Type */
     1680.m { color: #208050 } /* Literal.Number */
     1681.s { color: #4070a0 } /* Literal.String */
     1682.na { color: #4070a0 } /* Name.Attribute */
     1683.nb { color: #007020 } /* Name.Builtin */
     1684.nc { color: #0e84b5; font-weight: bold } /* Name.Class */
     1685.no { color: #60add5 } /* Name.Constant */
     1686.nd { color: #555555; font-weight: bold } /* Name.Decorator */
     1687.ni { color: #d55537; font-weight: bold } /* Name.Entity */
     1688.ne { color: #007020 } /* Name.Exception */
     1689.nf { color: #06287e } /* Name.Function */
     1690.nl { color: #002070; font-weight: bold } /* Name.Label */
     1691.nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
     1692.nt { color: #062873; font-weight: bold } /* Name.Tag */
     1693.nv { color: #bb60d5 } /* Name.Variable */
     1694.ow { color: #007020; font-weight: bold } /* Operator.Word */
     1695.w { color: #bbbbbb } /* Text.Whitespace */
     1696.mf { color: #208050 } /* Literal.Number.Float */
     1697.mh { color: #208050 } /* Literal.Number.Hex */
     1698.mi { color: #208050 } /* Literal.Number.Integer */
     1699.mo { color: #208050 } /* Literal.Number.Oct */
     1700.sb { color: #4070a0 } /* Literal.String.Backtick */
     1701.sc { color: #4070a0 } /* Literal.String.Char */
     1702.sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
     1703.s2 { color: #4070a0 } /* Literal.String.Double */
     1704.se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
     1705.sh { color: #4070a0 } /* Literal.String.Heredoc */
     1706.si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
     1707.sx { color: #c65d09 } /* Literal.String.Other */
     1708.sr { color: #235388 } /* Literal.String.Regex */
     1709.s1 { color: #4070a0 } /* Literal.String.Single */
     1710.ss { color: #517918 } /* Literal.String.Symbol */
     1711.bp { color: #007020 } /* Name.Builtin.Pseudo */
     1712.vc { color: #bb60d5 } /* Name.Variable.Class */
     1713.vg { color: #bb60d5 } /* Name.Variable.Global */
     1714.vi { color: #bb60d5 } /* Name.Variable.Instance */
     1715.il { color: #208050 } /* Literal.Number.Integer.Long */
     1716
     1717
     1718
    16381719"""
    16391720    if color == 'gmail':
    16401721        color1 = '#c3d9ff'
  • sage/server/notebook/js.py

    diff --git a/sage/server/notebook/js.py b/sage/server/notebook/js.py
    a b  
    10171017            halt_introspection();
    10181018            return;
    10191019        }
     1020
    10201021        d.innerHTML = introspection_text;
     1022
     1023        if (contains_jsmath(introspection_text)) {
     1024            try {
     1025                jsMath.ProcessBeforeShowing(d);
     1026            } catch(e) {
     1027                text_cell.innerHTML = jsmath_font_msg + d.innerHTML;
     1028            }
     1029        }
     1030
    10211031        if(replacing)
    10221032            select_replacement_element();
    10231033    } else {
     
    30163026        cell_output.innerHTML = '';
    30173027        cell_output_nowrap.innerHTML = '';
    30183028        cell_output_html.innerHTML = introspect_html;
     3029        if (contains_jsmath(introspect_html)) {
     3030            try {
     3031                jsMath.ProcessBeforeShowing(cell_output_html);
     3032            } catch(e) {
     3033                cell_output.innerHTML = jsmath_font_msg + cell_output_html.innerHTML;
     3034            }
     3035        }
     3036
    30193037    }
    30203038}
    30213039
  • sage/server/support.py

    diff --git a/sage/server/support.py b/sage/server/support.py
    a b  
    5353        sage.structure.sage_object.base=object_directory
    5454    sage.misc.latex.EMBEDDED_MODE = True
    5555    sage.misc.pager.EMBEDDED_MODE = True
     56    sage.misc.sageinspect.EMBEDDED_MODE = True
    5657
    5758    setup_systems(globs)
    5859    sage.misc.session.init(globs)
     
    188189    except (AttributeError, NameError, SyntaxError):
    189190        return "No object '%s' currently defined."%obj_name
    190191    s  = ''
     192    newline = "\n\n"  # blank line to start new paragraph
    191193    try:
    192194        filename = sageinspect.sage_getfile(obj)
    193195        #i = filename.find('site-packages/sage/')
    194196        #if i == -1:
    195         s += 'File:        %s\n'%filename
     197        s += '**File:** %s'%filename
     198        s += newline
    196199        #else:
    197200        #    file = filename[i+len('site-packages/sage/'):]
    198201        #    s += 'File:        <html><a href="src_browser?%s">%s</a></html>\n'%(file,file)
    199202    except TypeError:
    200203        pass
    201     s += 'Type:        %s\n'%type(obj)
    202     s += 'Definition:  %s\n'%sageinspect.sage_getdef(obj, obj_name)
    203     s += 'Docstring: \n%s\n'%sageinspect.sage_getdoc(obj, obj_name)
     204    s += '**Type:** %s'%type(obj)
     205    s += newline
     206    s += '**Definition:** %s'%sageinspect.sage_getdef(obj, obj_name)
     207    s += newline
     208    s += '**Docstring:**'
     209    s += newline
     210    s += sageinspect.sage_getdoc(obj, obj_name)
    204211    return s.rstrip()
    205212
    206213def source_code(s, globs, system='sage'):
     
    226233            return obj._sage_src_()
    227234        except:
    228235            pass
     236        newline = "\n\n"  # blank line to start new paragraph
     237        indent = "    "   # indent source code to mark it as a code block
     238
    229239        filename = sageinspect.sage_getfile(obj)
    230240        lines, lineno = sageinspect.sage_getsourcelines(obj, is_binary=False)
    231         src = ''.join(lines)
    232         src = sagedoc.format_src(src)
     241        src = indent.join(lines)
     242        src = indent + sagedoc.format_src(src)
    233243        if not lineno is None:
    234             src = "File: %s\nSource Code (starting at line %s):\n%s"%(filename, lineno, src)
    235         return src
     244            output = "**File:** %s"%filename
     245            output += newline
     246            output += "**Source Code** (starting at line %s)::"%lineno
     247            output += newline
     248            output += src
     249        return output
    236250   
    237251    except (TypeError, IndexError), msg:
    238252        print msg
  • deleted file doc/introspect/builder.py

    # HG changeset patch
    # User Tom Boothby <boothby@u.washington.edu>
    # Date 1242707716 25200
    # Node ID 124cc31a16eaebdf76435860b30bb9fea095d8df
    # Parent  3d7fce9264e936d6978bc1bc3f199b55fea431cd
    Suppress noisy sphinx messages.
    
    diff --git a/doc/introspect/builder.py b/doc/introspect/builder.py
    deleted file mode 100644
    + -  
    1 #!/usr/bin/env python
    2 import os, sys, subprocess, shutil, glob, optparse
    3 
    4 #We remove the current directory from sys.path right away
    5 #so that we import sage from the proper spot
    6 try:
    7     sys.path.remove(os.path.realpath(os.getcwd()))
    8 except:
    9     pass
    10 
    11 from sage.misc.cachefunc import cached_method
    12 
    13 ##########################################
    14 #                Options                 #
    15 ##########################################
    16 SAGE_DOC = os.environ['SAGE_DOC']
    17 LANGUAGES = ['en', 'fr']
    18 SPHINXOPTS  = ""
    19 PAPER       = ""
    20 
    21 if PAPER == "a4":
    22     PAPEROPTS = "-D latex_paper_size=a4"
    23 elif PAPER == "letter":
    24     PAPEROPTS = "-D latex_paper_size=letter"
    25 else:
    26     PAPEROPTS = ""
    27 
    28 #Note that this needs to have the doctrees dir   
    29 ALLSPHINXOPTS   = SPHINXOPTS + " " + PAPEROPTS + " . "
    30 
    31 
    32 ##########################################
    33 #          Utility Functions             #
    34 ##########################################
    35 def mkdir(path):
    36     """
    37     Makes the directory at path if it doesn't exist and returns the
    38     string path.
    39 
    40     EXAMPLES::
    41 
    42         sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
    43         sage: d = tmp_filename(); d
    44         '/.../tmp_...'
    45         sage: os.path.exists(d)
    46         False
    47         sage: dd = builder.mkdir(d)
    48         sage: d == dd
    49         True
    50         sage: os.path.exists(d)
    51         True
    52     """
    53     if not os.path.exists(path):
    54         os.makedirs(path)
    55     return path
    56 
    57 def copytree(src, dst, symlinks=False, ignore_errors=False):
    58     """
    59     Recursively copy a directory tree using copy2().
    60 
    61     The destination directory must not already exist.
    62     If exception(s) occur, an Error is raised with a list of reasons.
    63 
    64     If the optional symlinks flag is true, symbolic links in the
    65     source tree result in symbolic links in the destination tree; if
    66     it is false, the contents of the files pointed to by symbolic
    67     links are copied.
    68 
    69     XXX Consider this example code rather than the ultimate tool.
    70 
    71     """
    72     names = os.listdir(src)
    73     mkdir(dst)
    74     errors = []
    75     for name in names:
    76         srcname = os.path.join(src, name)
    77         dstname = os.path.join(dst, name)
    78         try:
    79             if symlinks and os.path.islink(srcname):
    80                 linkto = os.readlink(srcname)
    81                 os.symlink(linkto, dstname)
    82             elif os.path.isdir(srcname):
    83                 copytree(srcname, dstname, symlinks)
    84             else:
    85                 shutil.copy2(srcname, dstname)
    86             # XXX What about devices, sockets etc.?
    87         except (IOError, os.error), why:
    88             errors.append((srcname, dstname, str(why)))
    89         # catch the Error from the recursive copytree so that we can
    90         # continue with other files
    91         except shutil.Error, err:
    92             errors.extend(err.args[0])
    93     try:
    94         shutil.copystat(src, dst)
    95     except OSError, why:
    96         errors.extend((src, dst, str(why)))
    97     if errors and not ignore_errors:
    98         raise shutil.Error, errors
    99 
    100 
    101 
    102 ##########################################
    103 #             Builders                   #
    104 ##########################################
    105 def builder_helper(type):
    106     """
    107     Returns a function which builds the documentation for
    108     output type type.
    109     """
    110     def f(self):
    111         output_dir = self._output_dir(type)
    112         os.chdir(self.dir)
    113 
    114         build_command = 'sphinx-build'
    115         build_command += ' -b %s -d %s %s %s'%(type, self._doctrees_dir(),
    116                                                ALLSPHINXOPTS, output_dir)
    117         print build_command
    118         subprocess.call(build_command, shell=True)
    119 
    120         print "Build finished.  The built documents can be found in %s"%output_dir
    121        
    122     f.is_output_format = True
    123     return f
    124        
    125 
    126 class DocBuilder(object):
    127     def __init__(self, name, lang='en'):
    128         """
    129         INPUT:
    130            
    131         - ``name`` - the name of a subdirectory in SAGE_DOC, such as
    132           'tutorial' or 'bordeaux_2008'
    133 
    134         - ``lang`` - (default "en") the language of the document.
    135         """
    136         if '/' in name:
    137             lang, name = name.split(os.path.sep)
    138         self.name = name
    139         self.lang = lang
    140         self.dir = os.path.join(SAGE_DOC, lang, name)
    141 
    142         #Make sure the .static and .templates directories are there
    143         mkdir(os.path.join(self.dir, "static"))
    144         mkdir(os.path.join(self.dir, "templates"))
    145 
    146     def _output_dir(self, type):
    147         """
    148         Returns the directory where the output of type type is stored.
    149         If the directory does not exist, then it will automatically be
    150         created.
    151 
    152         EXAMPLES::
    153 
    154             sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
    155             sage: b = builder.DocBuilder('tutorial')
    156             sage: b._output_dir('html')
    157             '.../devel/sage/doc/output/html/en/tutorial'
    158         """
    159         return mkdir(os.path.join(SAGE_DOC, "output", type, self.lang, self.name))
    160 
    161     def _doctrees_dir(self):
    162         """
    163         Returns the directory where the doctrees are stored.  If the
    164         directory does not exist, then it will automatically be
    165         created.
    166 
    167         EXAMPLES::
    168 
    169             sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
    170             sage: b = builder.DocBuilder('tutorial')
    171             sage: b._doctrees_dir()
    172             '.../devel/sage/doc/output/doctrees/en/tutorial'
    173         """
    174         return mkdir(os.path.join(SAGE_DOC, "output", 'doctrees', self.lang, self.name))
    175 
    176     def _output_formats(self):
    177         """
    178         Returns a list of the possible output formats.
    179 
    180         EXAMPLES::
    181 
    182             sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
    183             sage: b = builder.DocBuilder('tutorial')
    184             sage: b._output_formats()
    185             ['changes', 'html', 'htmlhelp', 'json', 'latex', 'linkcheck', 'pickle', 'web']
    186 
    187         """
    188         #Go through all the attributes of self and check to
    189         #see which ones have an 'is_output_format' attribute.  These
    190         #are the ones created with builder_helper.
    191         output_formats = []
    192         for attr in dir(self):
    193             if hasattr(getattr(self, attr), 'is_output_format'):
    194                 output_formats.append(attr)
    195         output_formats.sort()
    196         return output_formats
    197 
    198     def pdf(self):
    199         """
    200         Builds the PDF files for this document.  This is done by first
    201         (re)-building the LaTeX output, going into that LaTeX
    202         directory, and running 'make all-pdf' there.
    203 
    204         EXAMPLES::
    205 
    206             sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
    207             sage: b = builder.DocBuilder('tutorial')
    208             sage: b.pdf() #not tested
    209         """
    210         self.latex()
    211         os.chdir(self._output_dir('latex'))
    212         subprocess.call('make all-pdf', shell=True)
    213 
    214         pdf_dir = self._output_dir('pdf')
    215         for pdf_file in glob.glob('*.pdf'):
    216             shutil.move(pdf_file, os.path.join(pdf_dir, pdf_file))
    217 
    218         print "Build finished.  The built documents can be found in %s"%pdf_dir             
    219 
    220     def clean(self, *args):
    221         """
    222         """
    223         import shutil
    224         shutil.rmtree(self._doctrees_dir())
    225         output_formats = list(args) if args else self._output_formats()
    226         for format in output_formats:
    227             shutil.rmtree(self._output_dir(format), ignore_errors=True)
    228        
    229     html = builder_helper('html')
    230     pickle = builder_helper('pickle')
    231     web = pickle
    232     json = builder_helper('json')                       
    233     htmlhelp = builder_helper('htmlhelp')
    234     latex = builder_helper('latex')
    235     changes = builder_helper('changes')
    236     linkcheck = builder_helper('linkcheck')
    237 
    238 class AllBuilder(object):
    239     """
    240     A class used to build all of the documentation.
    241     """
    242     def __getattr__(self, attr):
    243         """
    244         For any attributes not explicitly defined, we just go through
    245         all of the documents and call their attr.  For example,
    246         'AllBuilder().json()' will go through all of the documents
    247         and call the json() method on their builders.
    248         """
    249         from functools import partial
    250         return partial(self._wrapper, attr)
    251 
    252     def _wrapper(self, name, *args, **kwds):
    253         """
    254         This is the function which goes through all of the documents
    255         and does the actual building.
    256         """
    257         for document in self.get_all_documents():
    258             getattr(get_builder(document), name)(*args, **kwds)
    259 
    260     def get_all_documents(self):
    261         """
    262         Returns a list of all of the documents. A document is a directory within one of
    263         the language subdirectories of SAGE_DOC specified by the global LANGUAGES
    264         variable.
    265 
    266         EXAMPLES::
    267 
    268             sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
    269             sage: documents = builder.AllBuilder().get_all_documents()
    270             sage: 'en/tutorial' in documents
    271             True
    272         """
    273         documents = []
    274         for lang in LANGUAGES:
    275             for document in os.listdir(os.path.join(SAGE_DOC, lang)):
    276                 documents.append(os.path.join(lang, document))
    277         return documents
    278 
    279 class WebsiteBuilder(DocBuilder):
    280     def html(self):
    281         """
    282         After we've finished building the website index page, we copy
    283         everything one directory up.
    284         """
    285         DocBuilder.html(self)
    286         html_output_dir = self._output_dir('html')
    287         copytree(html_output_dir,
    288                  os.path.realpath(os.path.join(html_output_dir, '..')),
    289                  ignore_errors=False)
    290 
    291     def clean(self):
    292         """
    293         When we clean the output for the website index, we need to
    294         remove all of the HTML that were placed in the parent
    295         directory.
    296         """
    297         html_output_dir = self._output_dir('html')
    298         parent_dir = os.path.realpath(os.path.join(html_output_dir, '..'))
    299         for filename in os.listdir(html_output_dir):
    300             parent_filename = os.path.join(parent_dir, filename)
    301             if not os.path.exists(parent_filename):
    302                 continue
    303             if os.path.isdir(parent_filename):
    304                 shutil.rmtree(parent_filename, ignore_errors=True)
    305             else:
    306                 os.unlink(parent_filename)
    307 
    308         DocBuilder.clean(self)
    309 
    310 class ReferenceBuilder(DocBuilder):
    311     """
    312     This the class used to build the reference manual.  It is
    313     resposible for making sure the auto generated ReST files for the
    314     Sage library are up to date.
    315 
    316     When building any output, we must first go through and check
    317     to see if we need to update any of the autogenerated ReST
    318     files.  There are two cases where this would happen:
    319 
    320     1. A new module gets added to one of the toctrees.
    321    
    322     2. The actual module gets updated and possibly contains a new
    323        title.
    324     """
    325     def __init__(self, *args, **kwds):
    326         DocBuilder.__init__(self, *args, **kwds)
    327         self._wrap_builder_helpers()
    328 
    329     def _wrap_builder_helpers(self):
    330         from functools import partial, update_wrapper
    331         for attr in dir(self):
    332             if hasattr(getattr(self, attr), 'is_output_format'):
    333                 f = partial(self._wrapper, attr)
    334                 f.is_output_format = True
    335                 update_wrapper(f, getattr(self, attr))
    336                 setattr(self, attr, f)
    337    
    338     def _wrapper(self, build_type, *args, **kwds):
    339         """
    340         This is the wrapper around the builder_helper methods that
    341         goes through and makes sure things are up to date.
    342         """
    343         #Write the .rst files for newly included modules
    344         for module_name in self.get_newly_included_modules(save=True):
    345             self.write_auto_rest_file(module_name)
    346 
    347         #Update the .rst files for modified Python modules
    348         for module_name in self.get_modified_modules():
    349             self.write_auto_rest_file(module_name.replace(os.path.sep, '.'))
    350 
    351         #Copy over the custom .rst files from _sage
    352         _sage = os.path.join(self.dir, '_sage')
    353         if os.path.exists(_sage):
    354             copytree(_sage, os.path.join(self.dir, 'sage'))
    355                
    356         getattr(DocBuilder, build_type)(self, *args, **kwds)
    357    
    358     def cache_filename(self):
    359         """
    360         Returns the filename where the pickle of the dictionary of
    361         already generated .rst files is stored.
    362         """
    363         return os.path.join(self._doctrees_dir(), 'reference.pickle')
    364 
    365     @cached_method
    366     def get_cache(self):
    367         """
    368         Retreive the cache of already generated .rst files.  If it
    369         doesn't exist, then we just return an empty dictionary.
    370         """
    371         filename = self.cache_filename()
    372         if not os.path.exists(filename):
    373             return {}
    374 
    375         import cPickle
    376         file = open(self.cache_filename(), 'rb')
    377         cache = cPickle.load(file)
    378         file.close()
    379         return cache
    380        
    381 
    382     def save_cache(self):
    383         """
    384         Save the cache of already generated .rst files.
    385         """
    386         import cPickle
    387         file = open(self.cache_filename(), 'wb')
    388         cPickle.dump(self.get_cache(), file)
    389         file.close()
    390 
    391     def get_sphinx_environment(self):
    392         """
    393         Returns the Sphinx environment for this project.
    394         """
    395         from sphinx.environment import BuildEnvironment
    396         class Foo(object):
    397             pass
    398         config = Foo()
    399         config.values = []
    400 
    401         env_pickle = os.path.join(self._doctrees_dir(), 'environment.pickle')
    402         try:
    403             return BuildEnvironment.frompickle(config, env_pickle)
    404         except IOError:
    405             pass
    406                                            
    407     def get_modified_modules(self):
    408         """
    409         Returns an iterator for all the modules that have been modified
    410         since the docuementation was last built.
    411         """
    412         env = self.get_sphinx_environment()
    413         if env is None:
    414             return
    415         added, changed, removed = env.get_outdated_files(False)
    416         for name in changed:
    417             if name.startswith('sage'):
    418                 yield name
    419 
    420     def print_modified_modules(self):
    421         """
    422         Prints a list of all the modules that have been modified since
    423         the documentation was last built.
    424         """
    425         for module_name in self.get_modified_modules():
    426             print module_name
    427 
    428     def get_all_rst_files(self, exclude_sage=True):
    429         """
    430         Returns an iterator for all rst files which are not
    431         autogenerated.
    432         """
    433         for directory, subdirs, files in os.walk(self.dir):
    434             if exclude_sage and directory.startswith(os.path.join(self.dir, 'sage')):
    435                 continue
    436             for filename in files:
    437                 if not filename.endswith('.rst'):
    438                     continue
    439                 yield os.path.join(directory, filename)
    440 
    441     def get_all_included_modules(self):
    442         """
    443         Returns an iterator for all modules which are included in the
    444         reference manual.
    445         """
    446         for filename in self.get_all_rst_files():
    447             for module in self.get_modules(filename):
    448                 yield module
    449 
    450     def get_newly_included_modules(self, save=False):
    451         """
    452         Returns an iterator for all modules that appear in the
    453         toctrees that don't appear in the cache.
    454         """
    455         cache = self.get_cache()
    456         new_modules = []
    457         for module in self.get_all_included_modules():
    458             if module not in cache:
    459                 cache[module] = True
    460                 yield module
    461         if save:
    462             self.save_cache()
    463 
    464     def print_newly_included_modules(self):
    465         """
    466         Prints all of the modules that appear in the toctrees that
    467         don't appear in the cache.
    468         """
    469         for module_name in self.get_newly_included_modules():
    470             print module_name
    471 
    472     def get_modules(self, filename):
    473         """
    474         Given a filename for a .rst file, return an iterator for
    475         all of the autogenerated rst files that it includes.
    476         """
    477         #Create the regular expression used to detect an autogenerated file
    478         import re
    479         auto_re = re.compile('^\s*(..\/)*(sage\/[\w\/]*)\s*$')
    480 
    481         #Read the lines
    482         f = open(filename)
    483         lines = f.readlines()
    484         f.close()
    485 
    486         for line in lines:
    487             match = auto_re.match(line)
    488             if match:
    489                 yield match.group(2).replace(os.path.sep, '.')
    490                
    491     def get_module_docstring_title(self, module_name):
    492         """
    493         Returns the title of the module from its docstring.
    494         """
    495         #Try to import the module
    496         try:
    497             import sage.all
    498             __import__(module_name)
    499         except ImportError, err:
    500             raise
    501             print "Warning: could not import %s"%module_name
    502             print err
    503             return "UNABLE TO IMPORT MODULE"
    504         module = sys.modules[module_name]
    505 
    506         #Get the docstring
    507         doc = module.__doc__
    508         if doc is None:
    509             doc = module.doc if hasattr(module, 'doc') else ""
    510 
    511         #Extract the title
    512         i = doc.find('\n')
    513         if i != -1:
    514             return doc[i+1:].lstrip().splitlines()[0]
    515         else:
    516             return doc
    517 
    518     def write_auto_rest_file(self, module_name):
    519         """
    520         Writes the autogenerated .rst file for module_name.
    521         """
    522         if not module_name.startswith('sage'):
    523             return
    524         filename = self.dir + os.path.sep + module_name.replace('.',os.path.sep) + '.rst'
    525         mkdir(os.path.dirname(filename))
    526        
    527         outfile = open(filename, 'w')
    528 
    529         title = self.get_module_docstring_title(module_name)
    530 
    531         if title == '':
    532             print "WARNING: Missing title for", module_name
    533             title = "MISSING TITLE"
    534 
    535         outfile.write(title + '\n')
    536         outfile.write('='*len(title) + "\n\n")
    537         outfile.write('.. This file has been autogenerated.\n\n')
    538         automodule = '.. automodule:: %s\n   :members:\n   :undoc-members:\n\n'
    539         outfile.write(automodule%module_name)
    540 
    541         outfile.close()
    542 
    543     def clean_auto(self):
    544         """
    545         Remove the cache file for the autogenerated files as well as
    546         the files themselves.
    547         """
    548         if os.path.exists(self.cache_filename()):
    549             os.unlink(self.cache_filename())
    550 
    551         import shutil
    552         shutil.rmtree(self.dir + '/sage')
    553 
    554     def get_unincluded_modules(self):
    555         """
    556         Returns an iterator for all the modules in the Sage library
    557         which are not included in the reference manual.
    558         """
    559         #Make a dictionary of the included modules
    560         included_modules = {}
    561         for module_name in self.get_all_included_modules():
    562             included_modules[module_name] = True
    563        
    564         base_path = os.path.join(os.environ['SAGE_ROOT'], 'devel', 'sage', 'sage')
    565         for directory, subdirs, files in os.walk(base_path):
    566             for filename in files:
    567                 if not (filename.endswith('.py') or
    568                         filename.endswith('.pyx')):
    569                     continue
    570                
    571                 path = os.path.join(directory, filename)
    572 
    573                 #Create the module name
    574                 module_name = path[len(base_path):].replace(os.path.sep, '.')
    575                 module_name = 'sage' + module_name
    576                 module_name = module_name[:-4] if module_name.endswith('pyx') else module_name[:-3]
    577 
    578                 #Exclude some ones  -- we don't want init the manual
    579                 if module_name.endswith('__init__') or module_name.endswith('all'):
    580                     continue
    581 
    582                 if module_name not in included_modules:
    583                     yield module_name
    584                
    585     def print_unincluded_modules(self):
    586         """
    587         Prints all of the modules which are not included in the Sage
    588         reference manual.
    589         """
    590         for module_name in self.get_unincluded_modules():
    591             print module_name
    592 
    593     def print_included_modules(self):
    594         """
    595         Prints all of the modules that are included in the Sage reference
    596         manual.
    597         """
    598         for module_name in self.get_all_included_modules():
    599             print module_name
    600 
    601        
    602 
    603 def get_builder(name):
    604     """
    605     Returns a either a AllBuilder or DocBuilder object depending
    606     on whether ``name`` is 'all' or not.  These are the objects
    607     which do all the real work in building the documentation.
    608     """
    609     if name == 'all':
    610         return AllBuilder()
    611     elif name.endswith('reference'):
    612         return ReferenceBuilder(name)
    613     elif name.endswith('website'):
    614         return WebsiteBuilder(name)
    615     else:
    616         return DocBuilder(name)
    617              
    618 
    619 def help_message():
    620     """
    621     Returns the help message.
    622     """
    623     all_b = AllBuilder()
    624     docs = all_b.get_all_documents()
    625     docs = [(d[3:] if d[0:3] == 'en/' else d) for d in docs]
    626     tut_b = DocBuilder('en/tutorial')
    627     formats = tut_b._output_formats()
    628     formats.remove('html')
    629     help = "Usage: sage -docbuild {document} {format}\n"
    630     help += "Where {document} is one of:\n    "
    631     help += "\n    ".join(docs)
    632     help += "\nor 'all' for all documents, and {format} is one of:\n    "
    633     help += 'html, pdf, ' + ', '.join(formats)
    634     help += "\n"
    635     help += "When building the reference manual, there are several additional\n"
    636     help += "values for {format}:\n"
    637     help += "    print_modified_modules: list modules modified since the documentation\n"
    638     help += "         was last built\n"
    639     help += "    print_newly_included_modules: list modules added to the\n"
    640     help += "         documentation since it was last built\n"
    641     help += "    print_unincluded_modules: list modules not included in the documentation\n"
    642     help += "    print_included_modules: list modules included in the documentation\n"
    643     print help
    644 
    645 
    646 parser = optparse.OptionParser(usage="usage: sage -docbuild [options] name type")
    647 parser.add_option("--jsmath", action="store_true",
    648                   help="render math using jsMath")
    649 parser.print_help = help_message
    650 
    651 if __name__ == '__main__':
    652     options, args = parser.parse_args()
    653 
    654     if options.jsmath:
    655         os.environ['SAGE_DOC_JSMATH'] = "True"
    656 
    657     #Get the name of the document we are trying to build
    658     try:
    659         name, type = args
    660     except ValueError:
    661         print "You must specify the document name and the output format"
    662         sys.exit(0)
    663    
    664     #Make sure common/static exists
    665     mkdir(os.path.join(SAGE_DOC, 'common', 'static'))
    666 
    667     #Get the builder and build
    668     getattr(get_builder(name), type)()
  • sage/server/notebook/cell.py

    diff --git a/sage/server/notebook/cell.py b/sage/server/notebook/cell.py
    a b  
    15491549                confoverrides = {'html_context' : {}, 'master_doc' : hash}
    15501550
    15511551                # To suppress output, use this:
    1552 #                sphinx_app = Sphinx(srcdir, confdir, srcdir, doctreedir, 'html', confoverrides, None, None, True)
     1552                sphinx_app = Sphinx(srcdir, confdir, srcdir, doctreedir, 'html', confoverrides, None, None, True)
    15531553
    15541554                # For verbose output, use these instead:
    15551555                import sys
    1556                 sphinx_app = Sphinx(srcdir, confdir, srcdir, doctreedir, 'html', confoverrides, sys.stdout, sys.stderr, True)
     1556#                sphinx_app = Sphinx(srcdir, confdir, srcdir, doctreedir, 'html', confoverrides, sys.stdout, sys.stderr, True)
    15571557
    15581558                # Run Sphinx. The first argument corresponds to
    15591559                # sphinx-build's "write all files" -a flag, which we
  • sage/server/notebook/css.py

    diff --git a/sage/server/notebook/css.py b/sage/server/notebook/css.py
    a b  
    16521652
    16531653
    16541654
     1655/* These have been scraped directly from pygment. */
     1656
    16551657.hll { background-color: #ffffcc }
    16561658.c { color: #408090; font-style: italic } /* Comment */
    16571659.err { border: 1px solid #FF0000 } /* Error */
     
    17141716.vi { color: #bb60d5 } /* Name.Variable.Instance */
    17151717.il { color: #208050 } /* Literal.Number.Integer.Long */
    17161718
    1717 
     1719/* end stuff scraped from pygment */
    17181720
    17191721"""
    17201722    if color == 'gmail':
  • new file doc/en/introspect/conf.py

    # HG changeset patch
    # User Mitesh Patel <qed777@gmail.com>
    # Date 1242728269 25200
    # Node ID 1eacea743efa874ac44b1d67b0e0f074ecd8066b
    # Parent  124cc31a16eaebdf76435860b30bb9fea095d8df
    Move introspect config to doc/en/introspect, make relative to doc/common.
    
    diff --git a/doc/en/introspect/conf.py b/doc/en/introspect/conf.py
    new file mode 100644
    - +  
     1# -*- coding: utf-8 -*-
     2# Sage introspection build configuration file.
     3# See sage.server.notebook.cell.set_introspect_html() for details.
     4
     5import sys, os
     6sys.path.append(os.environ['SAGE_DOC'])
     7from common.conf import *
     8
     9extensions = ['sphinx.ext.autodoc', 'sphinx.ext.jsmath']
     10
     11templates_path = ['templates']
     12html_static_path = ['static']
     13
     14html_use_modindex = False
     15html_use_index = False
     16html_split_index = False
     17html_copy_source = False
  • new file doc/en/introspect/static/.empty

    diff --git a/doc/en/introspect/static/.empty b/doc/en/introspect/static/.empty
    new file mode 100644
    - +  
     1 
     2 No newline at end of file
  • new file doc/en/introspect/templates/layout.html

    diff --git a/doc/en/introspect/templates/layout.html b/doc/en/introspect/templates/layout.html
    new file mode 100644
    - +  
     1<div class="docstring">
     2    {% block body %} {% endblock %}
     3</div>
  • deleted file doc/introspect/__init__.py

    diff --git a/doc/introspect/__init__.py b/doc/introspect/__init__.py
    deleted file mode 100644
    + -  
    1  
  • deleted file doc/introspect/conf.py

    diff --git a/doc/introspect/conf.py b/doc/introspect/conf.py
    deleted file mode 100644
    + -  
    1 import sys, os
    2 SAGE_DOC = os.environ['SAGE_ROOT'] + '/devel/sage/doc'
    3 
    4 # If your extensions are in another directory, add it here. If the directory
    5 # is relative to the documentation root, use os.path.abspath to make it
    6 # absolute, like shown here.
    7 #sys.path.append(os.path.abspath('.'))
    8 
    9 # General configuration
    10 # ---------------------
    11 
    12 # Add any Sphinx extension module names here, as strings. They can be extensions
    13 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
    14 extensions = ['sphinx.ext.autodoc', 'sphinx.ext.jsmath']
    15 
    16 jsmath_path = '/javascript_local/jsmath/easy/load.js'
    17 
    18 # Add any paths that contain templates here, relative to this directory.
    19 templates_path = [SAGE_DOC + '/introspect/templates', 'templates']
    20 
    21 # The suffix of source filenames.
    22 source_suffix = '.rst'
    23 
    24 # The master toctree document.
    25 master_doc = 'index'
    26 
    27 # General information about the project.
    28 project = u""
    29 copyright = u'2008, The Sage Group'
    30 
    31 # The version info for the project you're documenting, acts as replacement for
    32 # |version| and |release|, also used in various other places throughout the
    33 # built documents.
    34 #
    35 # The short X.Y version.
    36 # from sage.version import version
    37 # release = version
    38 
    39 #version = '3.1.2'
    40 # The full version, including alpha/beta/rc tags.
    41 #release = '3.1.2'
    42 
    43 # The language for content autogenerated by Sphinx. Refer to documentation
    44 # for a list of supported languages.
    45 #language = None
    46 
    47 # There are two options for replacing |today|: either, you set today to some
    48 # non-false value, then it is used:
    49 #today = ''
    50 # Else, today_fmt is used as the format for a strftime call.
    51 #today_fmt = '%B %d, %Y'
    52 
    53 # List of documents that shouldn't be included in the build.
    54 #unused_docs = []
    55 
    56 # List of directories, relative to source directory, that shouldn't be searched
    57 # for source files.
    58 exclude_trees = ['.build']
    59 
    60 # The reST default role (used for this markup: `text`) to use for all documents.
    61 default_role = 'math'
    62 
    63 # If true, '()' will be appended to :func: etc. cross-reference text.
    64 #add_function_parentheses = True
    65 
    66 # If true, the current module name will be prepended to all description
    67 # unit titles (such as .. function::).
    68 #add_module_names = True
    69 
    70 # If true, sectionauthor and moduleauthor directives will be shown in the
    71 # output. They are ignored by default.
    72 #show_authors = False
    73 
    74 # The name of the Pygments (syntax highlighting) style to use.
    75 pygments_style = 'sphinx'
    76 
    77 
    78 # Options for HTML output
    79 # -----------------------
    80 
    81 # The style sheet to use for HTML and HTML Help pages. A file of that name
    82 # must exist either in Sphinx' static/ path, or in one of the custom paths
    83 # given in html_static_path.
    84 html_style = 'default.css'
    85 
    86 # The name for this set of Sphinx documents.  If None, it defaults to
    87 # "<project> v<release> documentation".
    88 #html_title = None
    89 
    90 # A shorter title for the navigation bar.  Default is the same as html_title.
    91 #html_short_title = None
    92 
    93 # The name of an image file (within the static path) to place at the top of
    94 # the sidebar.
    95 #html_logo = 'sagelogo-word.ico'
    96 
    97 # The name of an image file (within the static path) to use as favicon of the
    98 # docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
    99 # pixels large.
    100 # html_favicon = 'sageicon.png'
    101 
    102 # Add any paths that contain custom static files (such as style sheets) here,
    103 # relative to this directory. They are copied after the builtin static files,
    104 # so a file named "default.css" will overwrite the builtin "default.css".
    105 html_static_path = [SAGE_DOC +'/introspect/static', 'static']
    106 
    107 # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
    108 # using the given strftime format.
    109 #html_last_updated_fmt = '%b %d, %Y'
    110 
    111 # If true, SmartyPants will be used to convert quotes and dashes to
    112 # typographically correct entities.
    113 #html_use_smartypants = True
    114 
    115 # Custom sidebar templates, maps document names to template names.
    116 #html_sidebars = {}
    117 
    118 # Additional templates that should be rendered to pages, maps page names to
    119 # template names.
    120 #html_additional_pages = {}
    121 
    122 # If false, no module index is generated.
    123 html_use_modindex = False
    124 
    125 # If false, no index is generated.
    126 html_use_index = False
    127 
    128 # If true, the index is split into individual pages for each letter.
    129 #html_split_index = True
    130 
    131 # If true, the reST sources are included in the HTML build as _sources/<name>.
    132 html_copy_source = False
    133 
    134 # If true, an OpenSearch description file will be output, and all pages will
    135 # contain a <link> tag referring to it.  The value of this option must be the
    136 # base URL from which the finished HTML is served.
    137 #html_use_opensearch = ''
    138 
    139 # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
    140 #html_file_suffix = ''
    141 
    142 # Output file base name for HTML help builder.
    143 #htmlhelp_basename = ''
    144 
    145 
    146 # Options for LaTeX output
    147 # ------------------------
    148 
    149 # The paper size ('letter' or 'a4').
    150 #latex_paper_size = 'letter'
    151 
    152 # The font size ('10pt', '11pt' or '12pt').
    153 #latex_font_size = '10pt'
    154 
    155 # Grouping the document tree into LaTeX files. List of tuples
    156 # (source start file, target name, title, author, document class [howto/manual]).
    157 #latex_documents = []
    158 
    159 # The name of an image file (relative to this directory) to place at the top of
    160 # the title page.
    161 #latex_logo = 'sagelogo-word.png'
    162 
    163 # For "manual" documents, if this is true, then toplevel headings are parts,
    164 # not chapters.
    165 #latex_use_parts = False
    166 
    167 # Additional stuff for the LaTeX preamble.
    168 #latex_preamble = ''
    169 #latex_preamble = '\usepackage{amsmath}\n\usepackage{amsfonts}\n'
    170 
    171 # Documents to append as an appendix to all manuals.
    172 #latex_appendices = []
    173 
    174 # If false, no module index is generated.
    175 #latex_use_modindex = True
    176 
    177 
    178 #####################################################
    179 
    180 def process_docstring_aliases(app, what, name, obj, options, docstringlines):
    181     """
    182     Change the docstrings for aliases to point to the original object.
    183     """
    184     basename = name.rpartition('.')[2]
    185     if hasattr(obj, '__name__') and obj.__name__ != basename:
    186         docstringlines[:] = ['See :obj:`%s`.' % name]
    187 
    188 def process_docstring_cython(app, what, name, obj, options, docstringlines):
    189     """
    190     Remove Cython's filename and location embedding.
    191     """
    192     if len(docstringlines) <= 1:
    193         return
    194 
    195     first_line = docstringlines[0]
    196     if first_line.startswith('File:') and '(starting at' in first_line:
    197         #Remove the first two lines
    198         docstringlines.pop(0)
    199         docstringlines.pop(0)
    200 
    201 def process_docstring_module_title(app, what, name, obj, options, docstringlines):
    202     """
    203     Removes the first line from the beginning of the module's docstring.  This
    204     corresponds to the title of the module's documentation page.
    205     """
    206     if what != "module":
    207         return
    208 
    209     #Remove any additional blank lines at the beginning
    210     title_removed = False
    211     while len(docstringlines) > 1 and not title_removed:
    212         if docstringlines[0].strip() != "":
    213             title_removed = True
    214         docstringlines.pop(0)
    215 
    216     #Remove any additional blank lines at the beginning
    217     while len(docstringlines) > 1:
    218         if docstringlines[0].strip() == "":
    219             docstringlines.pop(0)
    220         else:
    221             break
    222 
    223        
    224 def setup(app):
    225     app.connect('autodoc-process-docstring', process_docstring_cython)
    226     app.connect('autodoc-process-docstring', process_docstring_module_title)
  • deleted file doc/introspect/static/.empty

    diff --git a/doc/introspect/static/.empty b/doc/introspect/static/.empty
    deleted file mode 100644
    + -  
    1  
    2  No newline at end of file
  • deleted file doc/introspect/templates/layout.html

    diff --git a/doc/introspect/templates/layout.html b/doc/introspect/templates/layout.html
    deleted file mode 100644
    + -  
    1 <div class="docstring">
    2     {% block body %} {% endblock %}
    3 </div>
  • sage/server/notebook/cell.py

    diff --git a/sage/server/notebook/cell.py b/sage/server/notebook/cell.py
    a b  
    3434
    3535import os, shutil
    3636
    37 from   sage.misc.misc import word_wrap, SAGE_ROOT
     37from   sage.misc.misc import word_wrap, SAGE_DOC
    3838from   sage.misc.html import math_parse
    3939from   sage.misc.preparser import strip_string_literals
    4040from   sage.misc.package   import is_package_installed
     
    15441544                # also pickles its environment in doctreedir, but we
    15451545                # force Sphinx never to load this pickle with
    15461546                # freshenv=True.
    1547                 confdir = os.path.join(SAGE_ROOT, 'devel/sage/doc/introspect')
     1547                confdir = os.path.join(SAGE_DOC, 'en/introspect')
    15481548                doctreedir = os.path.normpath(base_name)
    15491549                confoverrides = {'html_context' : {}, 'master_doc' : hash}
    15501550
     
    15521552                sphinx_app = Sphinx(srcdir, confdir, srcdir, doctreedir, 'html', confoverrides, None, None, True)
    15531553
    15541554                # For verbose output, use these instead:
    1555                 import sys
     1555#                import sys
    15561556#                sphinx_app = Sphinx(srcdir, confdir, srcdir, doctreedir, 'html', confoverrides, sys.stdout, sys.stderr, True)
    15571557
    15581558                # Run Sphinx. The first argument corresponds to