Package scons :: Module manuals
[hide private]
[frames] | no frames]

Source Code for Module scons.manuals

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2006,2008-2009,2011-2012,2015,2017-2019 Edward d'Auvergne     # 
  4  #                                                                             # 
  5  # This file is part of the program relax (http://www.nmr-relax.com).          # 
  6  #                                                                             # 
  7  # This program is free software: you can redistribute it and/or modify        # 
  8  # it under the terms of the GNU General Public License as published by        # 
  9  # the Free Software Foundation, either version 3 of the License, or           # 
 10  # (at your option) any later version.                                         # 
 11  #                                                                             # 
 12  # This program is distributed in the hope that it will be useful,             # 
 13  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
 14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
 15  # GNU General Public License for more details.                                # 
 16  #                                                                             # 
 17  # You should have received a copy of the GNU General Public License           # 
 18  # along with this program.  If not, see <http://www.gnu.org/licenses/>.       # 
 19  #                                                                             # 
 20  ############################################################################### 
 21   
 22  # Module docstring. 
 23  """SCons targets for building the relax manuals.""" 
 24   
 25  # Python module imports. 
 26  from datetime import datetime 
 27  from glob import glob 
 28  from os import F_OK, access, chdir, getcwd, listdir, path, remove, rename, sep, system 
 29  from re import search 
 30  from subprocess import PIPE, Popen 
 31  import sys 
 32   
 33  # relax module imports. 
 34  from info import Info_box 
 35  from status import Status; status = Status() 
 36  import version 
 37   
 38   
39 -def clean_manual_files(target, source, env):
40 """Builder action for removing the temporary manual files.""" 41 42 # Print out. 43 print('') 44 print("##########################################") 45 print("# Cleaning up the temporary manual files #") 46 print("##########################################\n\n") 47 48 # File list to remove. 49 files = [ 50 "relax.bbl", 51 "relax.blg", 52 "relax.dvi", 53 "relax.idx", 54 "relax.ilg", 55 "relax.ind", 56 "relax.lof", 57 "relax.log", 58 "relax.lot", 59 "relax.out", 60 "relax.toc", 61 "copyright.tex" 62 ] 63 64 # Add the LaTeX directory. 65 for i in range(len(files)): 66 files[i] = path.join(env['LATEX_DIR'], files[i]) 67 68 # LaTeX auxillary files. 69 for file in glob(env['LATEX_DIR'] + '*.aux'): 70 files.append(file) 71 for file in glob(env['LATEX_DIR'] + 'frame_order' + sep + '*.aux'): 72 files.append(file) 73 74 # Remove the files. 75 for file in files: 76 try: 77 remove(file) 78 except OSError: 79 message = sys.exc_info()[1] 80 81 # The file does not exist. 82 if message.errno == 2: 83 pass 84 85 # All other errors. 86 else: 87 raise 88 else: 89 print("Removing the file " + repr(file) + ".") 90 91 # Final printout. 92 print("\n\n\n")
93 94
95 -def compile_api_manual_html(target, source, env):
96 """Builder action for compiling the API documentation manual (HTML version) using Epydoc.""" 97 98 # Print out. 99 print('') 100 print("#####################################################") 101 print("# Compiling API documentation manual (HTML version) #") 102 print("#####################################################\n\n") 103 104 105 # Set up the Epydoc configuration (adapted from http://epydoc.sourceforge.net/configfile.html). 106 ############################################################################################### 107 108 # exclude 109 # The list of objects to exclude. 110 exclude = [ 111 'devel_scripts', 112 'extern', 113 'graphics', 114 'minfx.scipy_subset', 115 'multi.test_implementation', 116 'multi.test_implementation2', 117 'sample_scripts', 118 'test_suite.system_tests.scripts', 119 'test_suite.shared_data' 120 ] 121 122 # output 123 # The type of output that should be generated. Should be one 124 # of: html, text, latex, dvi, ps, pdf. 125 output = 'html' 126 127 # target 128 # The path to the output directory. May be relative or absolute. 129 target = 'docs'+sep+'api' 130 131 # docformat 132 # The default markup language for docstrings, for modules that do 133 # not define __docformat__. 134 docformat = 'epytext' 135 136 # css 137 # The CSS stylesheet for HTML output. Can be the name of a builtin 138 # stylesheet, or the name of a file. 139 css = 'white' 140 141 # name 142 # The documented project's name. 143 name = 'relax' 144 145 # url 146 # The documented project's URL. 147 url = 'http://www.nmr-relax.com' 148 149 # link 150 # HTML code for the project link in the navigation bar. If left 151 # unspecified, the project link will be generated based on the 152 # project's name and URL. 153 link = '<a href="/">relax</a>' 154 155 # top 156 # The "top" page for the documentation. Can be a URL, the name 157 # of a module or class, or one of the special names "trees.html", 158 # "indices.html", or "help.html" 159 # top = 'os.path' 160 161 # help 162 # An alternative help file. The named file should contain the 163 # body of an HTML file; navigation bars will be added to it. 164 # help = 'my_helpfile.html' 165 166 # frames 167 # Whether or not to include a frames-based table of contents. 168 frames = 1 169 170 # private 171 # Whether or not to inclue private variables. (Even if included, 172 # private variables will be hidden by default.) 173 private = 1 174 175 # imports 176 # Whether or not to list each module's imports. 177 imports = 1 178 179 # verbosity 180 # An integer indicating how verbose epydoc should be. The default 181 # value is 0; negative values will supress warnings and errors; 182 # positive values will give more verbose output. 183 verbosity = 1 184 185 # parse 186 # Whether or not parsing should be used to examine objects. 187 parse = 1 188 189 # introspect 190 # Whether or not introspection should be used to examine objects. 191 introspect = 1 192 193 # graph 194 # The list of graph types that should be automatically included 195 # in the output. Graphs are generated using the Graphviz "dot" 196 # executable. Graph types include: "classtree", "callgraph", 197 # "umlclass". Use "all" to include all graph types 198 graph = 'all' 199 200 # dotpath 201 # The path to the Graphviz "dot" executable, used to generate 202 # graphs. 203 #dotpath = '/usr/local/bin/dot' 204 205 # sourcecode 206 # Whether or not to include syntax highlighted source code in 207 # the output (HTML only). 208 sourcecode = 1 209 210 # pstat 211 # The name of one or more pstat files (generated by the profile 212 # or hotshot module). These are used to generate call graphs. 213 #pstat = 'profile.out' 214 215 # separate-classes 216 # Whether each class should be listed in its own section when 217 # generating LaTeX or PDF output. 218 #separate-classes = 0 219 220 221 222 # Construct the command line string. 223 #################################### 224 225 # Program name, output, target, docformat, css, name, and url. 226 epydoc_cmd = 'epydoc' + ' --' + output + ' -o ' + target + ' --docformat ' + docformat + ' --css ' + css + ' --name ' + name + ' --url ' + url + ' --simple-term' 227 if 'link' in locals(): 228 epydoc_cmd += ' --navlink \'%s\'' % link 229 230 # Frames. 231 if frames: 232 epydoc_cmd = epydoc_cmd + ' --show-frames' 233 else: 234 epydoc_cmd = epydoc_cmd + ' --no-frames' 235 236 # Private variables. 237 if private: 238 epydoc_cmd = epydoc_cmd + ' --show-private' 239 else: 240 epydoc_cmd = epydoc_cmd + ' --no-private' 241 242 # Module imports. 243 if imports: 244 epydoc_cmd = epydoc_cmd + ' --show-imports' 245 else: 246 epydoc_cmd = epydoc_cmd + ' --no-imports' 247 248 # Verbosity. 249 if verbosity > 0: 250 for i in range(verbosity): 251 epydoc_cmd = epydoc_cmd + ' -v' 252 elif verbosity < 0: 253 for i in range(-verbosity): 254 epydoc_cmd = epydoc_cmd + ' -q' 255 256 # Parsing and introspection. 257 if parse and not introspect: 258 epydoc_cmd = epydoc_cmd + ' --parse-only' 259 elif not parse and introspect: 260 epydoc_cmd = epydoc_cmd + ' --introspect-only' 261 262 # Graph. 263 epydoc_cmd = epydoc_cmd + ' --graph ' + graph 264 265 # Sourcecode. 266 if sourcecode: 267 epydoc_cmd = epydoc_cmd + ' --show-sourcecode' 268 else: 269 epydoc_cmd = epydoc_cmd + ' --no-sourcecode' 270 271 # Excluded modules. 272 for name in exclude: 273 epydoc_cmd = epydoc_cmd + ' --exclude=' + name 274 275 # Process all files and directories in the base relax directory. 276 blacklist = ['relax_gui_mode.py'] 277 files = listdir(getcwd()) 278 for file in files: 279 # Blacklisted. 280 if file in blacklist: 281 continue 282 283 # The excluded ones. 284 if file in exclude: 285 continue 286 287 # Hidden files and directories. 288 if search('^\.', file): 289 continue 290 291 # Not a Python file. 292 if not path.isdir(file) and not search('.py$', file): 293 continue 294 295 # Otherwise add it. 296 epydoc_cmd = "%s %s" % (epydoc_cmd, file) 297 298 299 # Execute Epydoc. 300 ################# 301 302 # Printout. 303 print("Running the command:\n$ " + epydoc_cmd + "\n\n\n") 304 305 # System call. 306 pipe = Popen(epydoc_cmd, shell=True, stdout=PIPE, stderr=PIPE, close_fds=False) 307 308 # Parse the output. 309 issues = [] 310 for line in pipe.stdout.readlines(): 311 if len(line.strip()) and line[0] in ['+', '|']: 312 # Printout. 313 sys.stdout.write(line) 314 315 # A new issue 316 if search("^\+----------", line): 317 issues.append("") 318 continue 319 320 # Append the text. 321 issues[-1] += line[2:].rstrip() 322 323 # Check for issues. 324 for issue in issues: 325 # Skip wxPython docstring errors (not import errors). 326 if "wx/" in issue: 327 continue 328 329 # Skip pystarlib docstring errors (not import errors). 330 if "pystarlib/" in issue: 331 continue 332 333 # Fail on everything else. 334 raise NameError("Errors or warnings found.") 335 336 337 # Modify the CSS file. 338 ###################### 339 340 # Open the file. 341 css_file = open(target + sep+'epydoc.css', 'a') 342 343 # Header. 344 css_file.write("\n\n\n\n/* Edward */\n\n") 345 346 # Append the new link style to the end. 347 css_file.write("a { text-decoration:none; color:#0017aa; font-weight:normal; }\n") 348 css_file.write("a:hover { color:#316fff; }\n") 349 350 # Close the file. 351 css_file.close() 352 353 354 # Modify all HTML files. 355 ######################## 356 357 # Print out. 358 print("\n\nModifying the header of all HTML files.\n") 359 360 # Copyright notice. 361 today = datetime.today() 362 creator = "Edward d'Auvergne" 363 copyright = """\ 364 <!-- 365 Copyright (C) %i %s 366 367 Permission is granted to copy, distribute and/or modify this document 368 under the terms of the GNU Free Documentation License, Version 1.3 369 or any later version published by the Free Software Foundation; 370 with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. 371 A copy of the license is included in the section titled "GNU 372 Free Documentation License" (fdl.html). 373 --> 374 """ % (today.year, creator) 375 376 # The additional head tags. 377 head_lines = [] 378 379 # The Google analytics JS. 380 file = open(status.install_path + sep + 'devel_scripts' + sep + 'google_analytics.js') 381 for line in file.readlines(): 382 head_lines.append(line) 383 file.close() 384 385 # Loop over the files. 386 for file_name in listdir(status.install_path + sep + 'docs' + sep + 'api'): 387 # The full path. 388 full_path = status.install_path + sep + 'docs' + sep + 'api' + sep + file_name 389 390 # Skip all non-html files. 391 if not search('.html$', full_path): 392 continue 393 394 # Open the file and read the data. 395 file = open(full_path) 396 lines = file.readlines() 397 file.close() 398 399 # Modify the original file. 400 file = open(full_path, 'w') 401 402 # Loop over the lines. 403 i = 0 404 while 1: 405 # Termination. 406 if i > len(lines)-1: 407 break 408 409 # Pre-header copyright notice insertion. 410 if search('<head>', lines[i]): 411 file.write(copyright) 412 413 # Header insertions (e.g. Google analytics JS). 414 if search('</head>', lines[i]): 415 start = False 416 for j in range(len(head_lines)): 417 # Skip the copyright notice. 418 if not start and search("Google analytics JS", head_lines[j]): 419 start = True 420 421 # Write out the rest. 422 if start: 423 file.write(head_lines[j]) 424 425 # Write out the content line. 426 file.write(lines[i]) 427 428 # Increment the line number. 429 i += 1 430 431 # Close the file. 432 file.close() 433 434 # Final printout. 435 print("\n\n\n")
436 437
438 -def compile_user_manual_html(target, source, env):
439 """Builder action for compiling the user manual (HTML version) from the LaTeX sources.""" 440 441 # Make the PDF manual to generate the aux files. 442 compile_user_manual_pdf(target, source, env, convert=False) 443 444 # Print out. 445 print('') 446 print("############################################") 447 print("# Compiling the user manual (HTML version) #") 448 print("############################################\n\n") 449 450 # Go to the LaTeX directory. 451 base_dir = getcwd() 452 chdir(env['LATEX_DIR']) 453 454 # The target directory. 455 dir = path.pardir + path.sep + "html" 456 457 # Run the latex2html command. 458 cmd = "latex2html -dir %s relax.tex" % (dir) 459 print("Running the command:\n$ %s\n\n\n" % cmd) 460 system(cmd) 461 462 # Create the proper index.html file. 463 cmd = "cp -vp %s%sThe_relax_user_manual.html %s%sindex.html" % (dir, path.sep, dir, path.sep) 464 print("Running the command:\n$ %s\n\n\n" % cmd) 465 system(cmd) 466 467 # Modify the CSS file. 468 css_file = open(path.join(dir, 'relax.css')) 469 css = css_file.readlines() 470 css_file.close() 471 css_file = open(path.join(dir, 'relax.css'), 'w') 472 for line in css: 473 # Fix the body width. 474 if search("^BODY { ", line): 475 css_file.write("BODY { width:95%; }\n") 476 477 # Preserve all other lines. 478 else: 479 css_file.write(line) 480 481 # Return to the base directory. 482 chdir(base_dir) 483 484 # Final printout. 485 print("\n\n\n")
486 487
488 -def compile_user_manual_pdf(target, source, env, convert=True):
489 """Builder action for compiling the user manual (PDF version) from the LaTeX sources.""" 490 491 # Print out. 492 print('') 493 print("###########################################") 494 print("# Compiling the user manual (PDF version) #") 495 print("###########################################\n\n") 496 497 # Go to the LaTeX directory. 498 base_dir = getcwd() 499 chdir(env['LATEX_DIR']) 500 501 print("\n\n\n <<< LaTeX (first round) >>>\n\n\n") 502 system('latex relax') 503 504 print("\n\n\n <<< Bibtex >>>\n\n\n") 505 system('bibtex relax') 506 507 print("\n\n\n <<< Makeindex >>>\n\n\n") 508 system('makeindex relax') 509 510 print("\n\n\n <<< LaTeX (second round) >>>\n\n\n") 511 system('latex relax') 512 513 print("\n\n\n <<< LaTeX (third round) >>>\n\n\n") 514 system('latex relax') 515 516 print("\n\n\n <<< Makeindex >>>\n\n\n") 517 system('makeindex relax') 518 519 print("\n\n\n <<< LaTeX (fourth round) >>>\n\n\n") 520 system('latex relax') 521 522 # Skip the rest. 523 if not convert: 524 # Return to the base directory. 525 chdir(base_dir) 526 527 # Return. 528 return 529 530 print("\n\n\n <<< dvips >>>\n\n\n") 531 system('dvips -R0 -o relax.ps relax.dvi') 532 533 print("\n\n\n <<< ps2pdf >>>\n\n\n") 534 if env['SYSTEM'] == 'Windows': 535 # According to the Ghostscript documentation, "When passing options to ghostcript through a batch 536 # file wrapper such as ps2pdf.bat you need to substitute '#' for '=' as the separator between options 537 # and their arguments." 538 assign = '#' 539 else: 540 assign = '=' 541 system('ps2pdf -dAutoFilterColorImages' + assign + 'false -dAutoFilterGrayImages' + assign + 'false -dColorImageFilter' + assign + '/FlateEncode -dColorImageFilter' + assign + '/FlateEncode -dGrayImageFilter' + assign + '/FlateEncode -dMonoImageFilter' + assign + '/FlateEncode -dPDFSETTINGS' + assign + '/prepress relax.ps relax.pdf') 542 543 print("\n\n\n <<< Removing the PS file and shifting the PDF down a directory >>>\n\n\n") 544 if access('relax.ps', F_OK): 545 remove('relax.ps') 546 if access('relax.pdf', F_OK): 547 rename('relax.pdf', path.pardir+path.sep+'relax.pdf') 548 549 # Return to the base directory. 550 chdir(base_dir) 551 552 # Final printout. 553 print("\n\n\n")
554 555 585 586
587 -def fetch_docstrings(target, source, env):
588 """Builder action for fetching the relax user function docstrings.""" 589 590 # Print out. 591 print('') 592 print("###############################################") 593 print("# Fetching the relax user function docstrings #") 594 print("###############################################\n\n") 595 596 # Import the fetch_docstrings module (needs to be done here so that Sconstruct doesn't need to load the entire program each time). 597 sys.path.insert(0, getcwd()) 598 from docs.latex.fetch_docstrings import Fetch_docstrings 599 600 # Get the docstrings. 601 Fetch_docstrings(env['LATEX_DIR'] + sep + 'docstring.tex') 602 603 # Delete the Fetch_docstrings class. This allows the loaded dll files to be deleted through python on MS Windows. 604 del Fetch_docstrings 605 606 # Final printout. 607 print("\n\n\n")
608 609
610 -def replicate_title_check(target, source, env):
611 """Builder action for checking for replicated titles in the LaTeX sources.""" 612 613 # Print out. 614 print('') 615 print("#######################################################") 616 print("# Checking for replicated titles in the LaTeX sources #") 617 print("#######################################################\n\n") 618 619 # Import the find_replicate_titles module (needs to be done here so that Sconstruct doesn't need to load the entire program each time). 620 sys.path.insert(0, getcwd()) 621 from docs.latex.find_replicate_titles import Replicated_titles 622 623 # Find the replicates. 624 replicates = Replicated_titles() 625 if replicates.find(): 626 print("\n\nFatal error: Replicated titles found.") 627 print("\n\n\n") 628 sys.exit(1) 629 630 # Delete the Replicate_titles class. This allows the loaded dll files to be deleted through python on MS Windows. 631 del replicates 632 del Replicated_titles 633 634 # Final printout. 635 print("No replicated titles found.") 636 print("\n\n\n")
637 638
639 -def version_file(target, source, env):
640 """Builder action for creating the LaTeX relax version file.""" 641 642 # Print out. 643 print('') 644 print("################################################") 645 print("# Creating the LaTeX relax version number file #") 646 print("################################################") 647 648 # Add the repository revision if not a normal release. 649 text = version.version 650 if text == 'repository commit': 651 if version.repo_type == 'git': 652 text += ' %s' % version.repo_head 653 else: 654 text += ' r%s' % version.repo_head 655 656 # Place the program version number into a LaTeX file. 657 file = open(env['LATEX_DIR'] + sep + 'relax_version.tex', 'w') 658 file.write("Version " + text + '\n') 659 file.close() 660 661 # Final printout. 662 print("\n\n\n")
663