Ticket #5653: docstring.4.patch
File docstring.4.patch, 54.4 KB (added by , 12 years ago) |
---|
-
new file doc/introspect/__init__.py
# HG changeset patch # User John H. Palmieri <palmieri@math.washington.edu> # Date 1240338630 25200 # Node ID 0e4cd3a9c85b54538dea576ee67ad0cc57a5ce2b # Parent 576345441a28e43ec773c3243233f490b8de2563 pretty docstrings in notebook diff -r 576345441a28 -r 0e4cd3a9c85b doc/introspect/__init__.py
- + 1 -
new file doc/introspect/builder.py
diff -r 576345441a28 -r 0e4cd3a9c85b doc/introspect/builder.py
- + 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)() -
new file doc/introspect/conf.py
diff -r 576345441a28 -r 0e4cd3a9c85b doc/introspect/conf.py
- + 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) -
new file doc/introspect/static/.empty
diff -r 576345441a28 -r 0e4cd3a9c85b doc/introspect/static/.empty
- + 1 2 No newline at end of file -
new file doc/introspect/templates/layout.html
diff -r 576345441a28 -r 0e4cd3a9c85b doc/introspect/templates/layout.html
- + 1 <div class="docstring"> 2 {% block body %} {% endblock %} 3 </div> -
sage/misc/sagedoc.py
diff -r 576345441a28 -r 0e4cd3a9c85b sage/misc/sagedoc.py
a b 20 20 #***************************************************************************** 21 21 22 22 import 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. 26 math_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', '...')] 38 nonmath_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: ')] 46 55 47 56 def _rmcmd(s, cmd, left='', right=''): 48 57 """ … … 112 121 itempattern = re.compile(r"\\item\[?([^]]*)\]? *(.*)") 113 122 itemreplace = r"* \1 \2" 114 123 115 def detex(s ):124 def detex(s, embedded=False): 116 125 """nodetex 117 126 This strips LaTeX commands from a string; it is used by the 118 127 ``format`` function to process docstrings for display from the 119 128 command line interface. 120 129 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``. 122 138 123 139 OUTPUT: string 124 140 … … 129 145 'Some math: `n >= k`. A website: sagemath.org.' 130 146 sage: detex(r'More math: `x \mapsto y`. {\bf Bold face}.') 131 147 '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`' 134 152 """ 135 153 s = _rmcmd(s, 'url') 136 154 s = _rmcmd(s, 'code') … … 142 160 s = _rmcmd(s, 'subsubsection') 143 161 s = _rmcmd(s, 'note', 'NOTE: ', '') 144 162 s = _rmcmd(s, 'emph', '*', '*') 163 s = _rmcmd(s, 'textbf', '*', '*') 145 164 146 165 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: 149 175 s = s.replace(a,b) 150 176 return s 151 177 152 def format(s ):178 def format(s, embedded=False): 153 179 """ 154 180 Format Sage documentation ``s`` for viewing with IPython. 155 181 … … 157 183 text, and if ``s`` contains a string of the form "<<<obj>>>", 158 184 then it replaces it with the docstring for "obj". 159 185 160 INPUT: ``s`` - string 186 INPUT: 187 188 - ``s`` - string 189 - ``embedded`` - boolean (optional, default False) 161 190 162 191 OUTPUT: string 163 192 193 Set ``embedded`` equal to True if formatting for use in the 194 notebook; this just gets passed as an argument to ``detex``. 195 164 196 EXAMPLES:: 165 197 166 198 sage: from sage.misc.sagedoc import format … … 216 248 t = 'Definition: ' + t0 + '\n\n' + t1 217 249 docs.add(obj) 218 250 s = s[:i] + '\n' + t + s[i+6+j:] 219 251 220 252 if 'nodetex' not in directives: 221 s = detex(s )253 s = detex(s, embedded=embedded) 222 254 return s 223 255 224 256 def format_src(s): -
sage/misc/sageinspect.py
diff -r 576345441a28 -r 0e4cd3a9c85b sage/misc/sageinspect.py
a b 114 114 115 115 import inspect 116 116 import os 117 EMBEDDED_MODE = False 117 118 118 119 def isclassinstance(obj): 119 120 r""" … … 400 401 if s[:4] == 'self': 401 402 s = s[4:] 402 403 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 403 431 return obj_name + '(' + s + ')' 404 432 except (AttributeError, TypeError, ValueError): 405 433 return '%s( [noargspec] )'%obj_name … … 439 467 440 468 if r is None: 441 469 return '' 442 s = sage.misc.sagedoc.format(str(r)) 470 471 s = sage.misc.sagedoc.format(str(r), embedded=EMBEDDED_MODE) 443 472 444 473 # If there is a Cython embedded position, it needs to be stripped 445 474 pos = _extract_embedded_position(s) -
sage/server/notebook/cell.py
diff -r 576345441a28 -r 0e4cd3a9c85b sage/server/notebook/cell.py
a b 34 34 35 35 import os, shutil 36 36 37 from sage.misc.misc import word_wrap 37 from sage.misc.misc import word_wrap, SAGE_ROOT 38 38 from sage.misc.html import math_parse 39 39 from sage.misc.preparser import strip_string_literals 40 40 from sage.misc.package import is_package_installed … … 46 46 else: 47 47 JEDITABLE_TINYMCE = False 48 48 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 52 import errno, hashlib, time 53 from sphinx.application import Sphinx 54 49 55 50 56 class Cell_generic: 51 57 def is_interactive_cell(self): … … 1431 1437 # Introspection # 1432 1438 ################# 1433 1439 def set_introspect_html(self, html, completing=False): 1434 if completing:1440 if html == "" or completing: 1435 1441 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>' 1436 1455 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 1439 1589 1440 1590 def introspect_html(self): 1441 1591 if not self.introspect(): -
sage/server/notebook/css.py
diff -r 576345441a28 -r 0e4cd3a9c85b sage/server/notebook/css.py
a b 293 293 div.introspection { 294 294 } 295 295 296 div.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 305 pre.literal-block { 306 background-color: #efc; 307 color: blue; 308 } 309 296 310 pre.introspection { 297 311 font-family: monospace; 298 312 font-size:15px; 299 background-color: #efefef; 313 background-color: #f1f1f1; 314 color: blue; 300 315 border: solid 1px black; 301 316 padding:8px; 302 317 margin:8px; … … 1635 1650 background-color: #990000; 1636 1651 } 1637 1652 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 1638 1719 """ 1639 1720 if color == 'gmail': 1640 1721 color1 = '#c3d9ff' -
sage/server/notebook/js.py
diff -r 576345441a28 -r 0e4cd3a9c85b sage/server/notebook/js.py
a b 1017 1017 halt_introspection(); 1018 1018 return; 1019 1019 } 1020 1020 1021 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 1021 1031 if(replacing) 1022 1032 select_replacement_element(); 1023 1033 } else { … … 2993 3003 cell_output.innerHTML = ''; 2994 3004 cell_output_nowrap.innerHTML = ''; 2995 3005 cell_output_html.innerHTML = introspect_html; 3006 if (contains_jsmath(introspect_html)) { 3007 try { 3008 jsMath.ProcessBeforeShowing(cell_output_html); 3009 } catch(e) { 3010 cell_output.innerHTML = jsmath_font_msg + cell_output_html.innerHTML; 3011 } 3012 } 3013 2996 3014 } 2997 3015 } 2998 3016 -
sage/server/support.py
diff -r 576345441a28 -r 0e4cd3a9c85b sage/server/support.py
a b 53 53 sage.structure.sage_object.base=object_directory 54 54 sage.misc.latex.EMBEDDED_MODE = True 55 55 sage.misc.pager.EMBEDDED_MODE = True 56 sage.misc.sageinspect.EMBEDDED_MODE = True 56 57 57 58 setup_systems(globs) 58 59 sage.misc.session.init(globs) … … 188 189 except (AttributeError, NameError, SyntaxError): 189 190 return "No object '%s' currently defined."%obj_name 190 191 s = '' 192 newline = "\n\n" # blank line to start new paragraph 191 193 try: 192 194 filename = sageinspect.sage_getfile(obj) 193 195 #i = filename.find('site-packages/sage/') 194 196 #if i == -1: 195 s += 'File: %s\n'%filename 197 s += '**File:** %s'%filename 198 s += newline 196 199 #else: 197 200 # file = filename[i+len('site-packages/sage/'):] 198 201 # s += 'File: <html><a href="src_browser?%s">%s</a></html>\n'%(file,file) 199 202 except TypeError: 200 203 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) 204 211 return s.rstrip() 205 212 206 213 def source_code(s, globs, system='sage'): … … 226 233 return obj._sage_src_() 227 234 except: 228 235 pass 236 newline = "\n\n" # blank line to start new paragraph 237 indent = " " # indent source code to mark it as a code block 238 229 239 filename = sageinspect.sage_getfile(obj) 230 240 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) 233 243 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 236 250 237 251 except (TypeError, IndexError), msg: 238 252 print msg