From cd704f74bb119c7d3bbe68cb4818cc799b28021b Mon Sep 17 00:00:00 2001 From: mdipierro Date: Sun, 25 Aug 2013 20:29:54 -0500 Subject: [PATCH] moved lots of files --- Makefile | 4 +- README.markdown | 4 +- VERSION | 2 +- doc/Makefile | 88 -- doc/convert_faq.py | 42 - doc/generate_modules.py | 258 ------ doc/make-doc_html.bat | 3 - doc/make-doc_html.sh | 3 - doc/make.bat | 112 --- doc/problematic_files.rst | 7 - doc/source/_static/pics/logo.png | Bin 41466 -> 0 bytes doc/source/_static/pics/logo_colored.png | Bin 15988 -> 0 bytes .../_static/pics/logo_colored_small.png | Bin 17766 -> 0 bytes doc/source/_static/pics/logo_small.jpg | Bin 13421 -> 0 bytes doc/source/_static/pics/logo_small.png | Bin 17390 -> 0 bytes doc/source/_static/rst/external_hint.txt | 22 - doc/source/conf.py | 251 ----- doc/source/docs_contrib.rst | 100 -- doc/source/faq.rst | 9 - doc/source/glossary.rst | 15 - doc/source/gluon/gluon.compat.rst | 13 - doc/source/gluon/gluon.contrib.gateways.rst | 13 - doc/source/gluon/gluon.contrib.markdown.rst | 21 - doc/source/gluon/gluon.contrib.memcache.rst | 21 - doc/source/gluon/gluon.contrib.pyrtf.rst | 53 -- doc/source/gluon/gluon.contrib.rst | 80 -- doc/source/gluon/gluon.contrib.simplejson.rst | 37 - doc/source/gluon/gluon.rst | 220 ----- doc/source/index.rst | 91 -- doc/source/modules.rst | 10 - doc/source/user_wiki.rst | 6 - doc/source/web2py_todo.rst | 28 - doc/sphinxext/local/generate_modules.py | 258 ------ doc/sphinxext/local/generate_modules_modif.py | 271 ------ doc/sphinxext/local/sphinx_tools.py | 87 -- doc/sphinxext/numpydoc/LICENSE.txt | 97 -- doc/sphinxext/numpydoc/MANIFEST.in | 2 - doc/sphinxext/numpydoc/__init__.py | 1 - doc/sphinxext/numpydoc/autosummary.py | 349 ------- .../numpydoc/autosummary_generate.py | 219 ----- doc/sphinxext/numpydoc/comment_eater.py | 158 ---- doc/sphinxext/numpydoc/compiler_unparse.py | 860 ------------------ doc/sphinxext/numpydoc/docscrape.py | 497 ---------- doc/sphinxext/numpydoc/docscrape_sphinx.py | 149 --- doc/sphinxext/numpydoc/numpydoc.py | 117 --- doc/sphinxext/numpydoc/only_directives.py | 96 -- doc/sphinxext/numpydoc/phantom_import.py | 162 ---- doc/sphinxext/numpydoc/plot_directive.py | 477 ---------- doc/sphinxext/numpydoc/setup.py | 31 - .../numpydoc/tests/test_docscrape.py | 490 ---------- examples/README | 2 + app.example.yaml => examples/app.example.yaml | 0 .../appengine_config.example.py | 0 .../logging.example.conf | 0 .../queue.example.yaml | 0 .../router.example.py | 0 .../routes.example.py | 0 .../build_web2py/setup_app.py | 0 .../build_web2py/setup_exe.conf | 0 .../build_web2py/setup_exe.py | 0 epydoc.conf => extras/epydoc/epydoc.conf | 2 +- epydoc.css => extras/epydoc/epydoc.css | 0 splashlogo.gif => extras/icons/splashlogo.gif | Bin web2py.gif => extras/icons/web2py.gif | Bin web2py.icns => extras/icons/web2py.icns | Bin web2py.ico => extras/icons/web2py.ico | Bin gluon/widget.py | 4 +- mkweb2pyenv | 27 - runweb2py | 24 - storage.sqlite | 0 w2p_apps | 27 - w2p_clone | 55 -- w2p_run | 24 - 73 files changed, 11 insertions(+), 5988 deletions(-) delete mode 100755 doc/Makefile delete mode 100755 doc/convert_faq.py delete mode 100755 doc/generate_modules.py delete mode 100755 doc/make-doc_html.bat delete mode 100755 doc/make-doc_html.sh delete mode 100755 doc/make.bat delete mode 100755 doc/problematic_files.rst delete mode 100755 doc/source/_static/pics/logo.png delete mode 100755 doc/source/_static/pics/logo_colored.png delete mode 100755 doc/source/_static/pics/logo_colored_small.png delete mode 100755 doc/source/_static/pics/logo_small.jpg delete mode 100755 doc/source/_static/pics/logo_small.png delete mode 100755 doc/source/_static/rst/external_hint.txt delete mode 100755 doc/source/conf.py delete mode 100755 doc/source/docs_contrib.rst delete mode 100755 doc/source/faq.rst delete mode 100755 doc/source/glossary.rst delete mode 100755 doc/source/gluon/gluon.compat.rst delete mode 100755 doc/source/gluon/gluon.contrib.gateways.rst delete mode 100755 doc/source/gluon/gluon.contrib.markdown.rst delete mode 100755 doc/source/gluon/gluon.contrib.memcache.rst delete mode 100755 doc/source/gluon/gluon.contrib.pyrtf.rst delete mode 100755 doc/source/gluon/gluon.contrib.rst delete mode 100755 doc/source/gluon/gluon.contrib.simplejson.rst delete mode 100755 doc/source/gluon/gluon.rst delete mode 100755 doc/source/index.rst delete mode 100755 doc/source/modules.rst delete mode 100755 doc/source/user_wiki.rst delete mode 100755 doc/source/web2py_todo.rst delete mode 100755 doc/sphinxext/local/generate_modules.py delete mode 100755 doc/sphinxext/local/generate_modules_modif.py delete mode 100755 doc/sphinxext/local/sphinx_tools.py delete mode 100755 doc/sphinxext/numpydoc/LICENSE.txt delete mode 100755 doc/sphinxext/numpydoc/MANIFEST.in delete mode 100755 doc/sphinxext/numpydoc/__init__.py delete mode 100755 doc/sphinxext/numpydoc/autosummary.py delete mode 100755 doc/sphinxext/numpydoc/autosummary_generate.py delete mode 100755 doc/sphinxext/numpydoc/comment_eater.py delete mode 100755 doc/sphinxext/numpydoc/compiler_unparse.py delete mode 100755 doc/sphinxext/numpydoc/docscrape.py delete mode 100755 doc/sphinxext/numpydoc/docscrape_sphinx.py delete mode 100755 doc/sphinxext/numpydoc/numpydoc.py delete mode 100755 doc/sphinxext/numpydoc/only_directives.py delete mode 100755 doc/sphinxext/numpydoc/phantom_import.py delete mode 100755 doc/sphinxext/numpydoc/plot_directive.py delete mode 100755 doc/sphinxext/numpydoc/setup.py delete mode 100755 doc/sphinxext/numpydoc/tests/test_docscrape.py create mode 100644 examples/README rename app.example.yaml => examples/app.example.yaml (100%) rename appengine_config.example.py => examples/appengine_config.example.py (100%) rename logging.example.conf => examples/logging.example.conf (100%) rename queue.example.yaml => examples/queue.example.yaml (100%) rename router.example.py => examples/router.example.py (100%) rename routes.example.py => examples/routes.example.py (100%) rename setup_app.py => extras/build_web2py/setup_app.py (100%) rename setup_exe.conf => extras/build_web2py/setup_exe.conf (100%) rename setup_exe.py => extras/build_web2py/setup_exe.py (100%) rename epydoc.conf => extras/epydoc/epydoc.conf (96%) rename epydoc.css => extras/epydoc/epydoc.css (100%) rename splashlogo.gif => extras/icons/splashlogo.gif (100%) rename web2py.gif => extras/icons/web2py.gif (100%) rename web2py.icns => extras/icons/web2py.icns (100%) rename web2py.ico => extras/icons/web2py.ico (100%) delete mode 100755 mkweb2pyenv delete mode 100644 runweb2py delete mode 100644 storage.sqlite delete mode 100755 w2p_apps delete mode 100755 w2p_clone delete mode 100755 w2p_run diff --git a/Makefile b/Makefile index aa14e01b..e490ea61 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ clean: epydoc: ### build epydoc rm -f -r applications/examples/static/epydoc/ - epydoc --config epydoc.conf + epydoc --config extras/epydoc/epydoc.conf cp applications/examples/static/title.png applications/examples/static/epydoc tests: python web2py.py --run_system_tests @@ -54,7 +54,7 @@ src: ### build web2py_src.zip echo '' > NEWINSTALL mv web2py_src.zip web2py_src_old.zip | echo 'no old' - cd ..; zip -r web2py/web2py_src.zip web2py/gluon/*.py web2py/gluon/contrib/* web2py/splashlogo.gif web2py/*.py web2py/README.markdown web2py/LICENSE web2py/CHANGELOG web2py/NEWINSTALL web2py/VERSION web2py/Makefile web2py/epydoc.css web2py/epydoc.conf web2py/app.example.yaml web2py/logging.example.conf web2py/queue.example.yaml web2py/MANIFEST.in web2py/w2p_apps web2py/w2p_clone web2py/w2p_run web2py/web2py.cio web2py/web2py.gif web2py/scripts/*.sh web2py/scripts/*.py web2py/applications/admin web2py/applications/examples/ web2py/applications/welcome web2py/applications/__init__.py web2py/site-packages/__init__.py web2py/gluon/tests/*.sh web2py/gluon/tests/*.py + cd ..; zip -r web2py/web2py_src.zip web2py/gluon/*.py web2py/gluon/contrib/* web2py/extras/* web2py/examples/* web2py/README.markdown web2py/LICENSE web2py/CHANGELOG web2py/NEWINSTALL web2py/VERSION web2py/MANIFEST.in web2py/scripts/*.sh web2py/scripts/*.py web2py/applications/admin web2py/applications/examples/ web2py/applications/welcome web2py/applications/__init__.py web2py/site-packages/__init__.py web2py/gluon/tests/*.sh web2py/gluon/tests/*.py mdp: make src diff --git a/README.markdown b/README.markdown index a9c8abab..68df1875 100644 --- a/README.markdown +++ b/README.markdown @@ -33,7 +33,7 @@ That's it!!! ... > other handlers and example files gluon/ > the core libraries contrib/ > third party libraries - tests/ > unittests + tests/ > unittests applications/ > are the apps admin/ > web based IDE ... @@ -54,6 +54,8 @@ That's it!!! cron/ tests/ ... > your own apps + examples/ > example config files, mv .. and customize + extras/ > other files which are required for building web2py scripts/ > utility and installation scripts site-packages/ > additional optional modules diff --git a/VERSION b/VERSION index c42f638d..bc05fd06 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.6.0-development+timestamp.2013.08.25.19.34.35 +Version 2.6.0-development+timestamp.2013.08.25.20.29.04 diff --git a/doc/Makefile b/doc/Makefile deleted file mode 100755 index 8f793c40..00000000 --- a/doc/Makefile +++ /dev/null @@ -1,88 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source - -.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - -rm -rf build/* - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) build/html - @echo - @echo "Build finished. The HTML pages are in build/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) build/dirhtml - @echo - @echo "Build finished. The HTML pages are in build/dirhtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) build/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) build/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) build/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in build/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) build/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in build/qthelp, like this:" - @echo "# qcollectiongenerator build/qthelp/Web2Py.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile build/qthelp/Web2Py.qhc" - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) build/latex - @echo - @echo "Build finished; the LaTeX files are in build/latex." - @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ - "run these through (pdf)latex." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) build/changes - @echo - @echo "The overview file is in build/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) build/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in build/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) build/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in build/doctest/output.txt." diff --git a/doc/convert_faq.py b/doc/convert_faq.py deleted file mode 100755 index e55490a6..00000000 --- a/doc/convert_faq.py +++ /dev/null @@ -1,42 +0,0 @@ -"""Convert a FAQ (AlterEgo) markdown dump into ReSt documents using pandoc - -**Todo** -#. add titles -#. add logging -#. add CLI with optparse -""" - - -import os -import sys -import glob -import subprocess -import logging - -indir = 'faq_markdown' -outdir = 'faq_rst' - -inpath = os.path.join('.', indir) -outpath = os.path.join('.', outdir) - -pattern = inpath + '/*.txt' -out_ext = 'rst' - - -for file in glob.glob(pattern): - infile = file - file_basename = os.path.basename(file) - outfile_name = os.path.splitext(file_basename)[0] + '.' + out_ext - outfile = os.path.join(outpath, outfile_name) - # pandoc -s -w rst --toc README -o example6.text - logging.info("converting file %s to format <%s>" % (file_basename, out_ext)) - convert_call = ["pandoc", - "-s", - "-w", out_ext, - infile, - "-o", outfile - ] - p = subprocess.call(convert_call) - -logging.info("Finshed!") - diff --git a/doc/generate_modules.py b/doc/generate_modules.py deleted file mode 100755 index 62c66440..00000000 --- a/doc/generate_modules.py +++ /dev/null @@ -1,258 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Sropulpof -# Copyright (C) 2008 Société des arts technologiques (SAT) -# http://www.sat.qc.ca -# All rights reserved. -# -# This file is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# Sropulpof is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Sropulpof. If not, see . - -""" -This script parse a directory tree looking for python modules and packages and -create ReST files appropriately to create code documentation with Sphinx. -It also create a modules index. -""" - -import os -import optparse - - -# automodule options -options = ['members', - 'undoc-members', -# 'inherited-members', # disable because there's a bug in sphinx - 'show-inheritance'] - -def create_file_name(base, opts): - """Create file name from base name, path and suffix""" - return os.path.join(opts.destdir, "%s.%s" % (base, opts.suffix)) - -def write_directive(module): - """Create the automodule directive and add the options""" - directive = '.. automodule:: %s\n' % module - for option in options: - directive += ' :%s:\n' % option - return directive - -def write_heading(module, kind='Module'): - """Create the page heading.""" - module = module.title() - heading = title_line(module + ' Documentation', '=') - heading += 'This page contains the %s %s documentation.\n\n' % (module, kind) - return heading - -def write_sub(module, kind='Module'): - """Create the module subtitle""" - sub = title_line('The :mod:`%s` %s' % (module, kind), '-') - return sub - -def title_line(title, char): - """ Underline the title with the character pass, with the right length.""" - return '%s\n%s\n\n' % (title, len(title) * char) - -def create_module_file(root, module, opts): - """Build the text of the file and write the file.""" - name = create_file_name(module, opts) - if not opts.force and os.path.isfile(name): - print 'File %s already exists.' % name - elif check_for_code('%s/%s.py' % (root, module)): # don't build the file if there's no code in it - print 'Creating file %s for module.' % name - text = write_heading(module) - text += write_sub(module) - text += write_directive(module) - - # write the file - if not opts.dryrun: - fd = open(name, 'w') - fd.write(text) - fd.close() - -def create_package_file(root, subroot, py_files, opts, subs=None): - """Build the text of the file and write the file.""" - package = root.rpartition('/')[2].lower() - name = create_file_name(subroot, opts) - if not opts.force and os.path.isfile(name): - print 'File %s already exists.' % name - else: - print 'Creating file %s for package.' % name - text = write_heading(package, 'Package') - if subs == None: - subs = [] - else: - # build a list of directories that are package (they contain an __init_.py file) - subs = [sub for sub in subs if os.path.isfile('%s/%s/__init__.py' % (root, sub))] - # if there's some package directories, add a TOC for theses subpackages - if subs: - text += title_line('Subpackages', '-') - text += '.. toctree::\n\n' - for sub in subs: - text += ' %s.%s\n' % (subroot, sub) - text += '\n' - - # add each package's module - for py_file in py_files: - if not check_for_code('%s/%s' % (root, py_file)): - # don't build the file if there's no code in it - continue - py_file = py_file[:-3] - py_path = '%s.%s' % (subroot, py_file) - kind = "Module" - if py_file == '__init__': - kind = "Package" - text += write_sub(kind == 'Package' and package or py_file, kind) - text += write_directive(kind == "Package" and subroot or py_path) - text += '\n' - - # write the file - if not opts.dryrun: - fd = open(name, 'w') - fd.write(text) - fd.close() - -def check_for_code(module): - """ - Check if there's at least one class or one function in the module. - """ - fd = open(module, 'r') - for line in fd: - if line.startswith('def ') or line.startswith('class '): - fd.close() - return True - fd.close() - return False - -def recurse_tree(path, excludes, opts): - """ - Look for every file in the directory tree and create the corresponding - ReST files. - """ - toc = [] - excludes = format_excludes(path, excludes) - tree = os.walk(path, False) - for root, subs, files in tree: - # keep only the Python script files - py_files = check_py_file(files) - # remove hidden ('.') and private ('_') directories - subs = [sub for sub in subs if sub[0] not in ['.', '_']] - # check if there's valid files to process - if "/." in root or "/_" in root \ - or not py_files \ - or check_excludes(root, excludes): - continue - subroot = root[len(path):].lstrip('/').replace('/', '.') - if root == path: - # we are at the root level so we create only modules - for py_file in py_files: - module = py_file[:-3] - create_module_file(root, module, opts) - toc.append(module) - elif not subs and "__init__.py" in py_files: - # we are in a package without sub package - create_package_file(root, subroot, py_files, opts=opts) - toc.append(subroot) - elif "__init__.py" in py_files: - # we are in package with subpackage(s) - create_package_file(root, subroot, py_files, opts, subs) - toc.append(subroot) - - # create the module's index - if not opts.notoc: - modules_toc(toc, opts) - -def modules_toc(modules, opts, name='modules'): - """ - Create the module's index. - """ - fname = create_file_name(name, opts) - if not opts.force and os.path.exists(fname): - print "File %s already exists." % name - return - - print "Creating module's index modules.txt." - text = write_heading(opts.header, 'Modules') - text += title_line('Modules:', '-') - text += '.. toctree::\n' - text += ' :maxdepth: %s\n\n' % opts.maxdepth - - modules.sort() - prev_module = '' - for module in modules: - # look if the module is a subpackage and, if yes, ignore it - if module.startswith(prev_module + '.'): - continue - prev_module = module - text += ' %s\n' % module - - # write the file - if not opts.dryrun: - fd = open(fname, 'w') - fd.write(text) - fd.close() - -def format_excludes(path, excludes): - """ - Format the excluded directory list. - (verify that the path is not from the root of the volume or the root of the - package) - """ - f_excludes = [] - for exclude in excludes: - if exclude[0] != '/' and exclude[:len(path)] != path: - exclude = '%s/%s' % (path, exclude) - # remove trailing slash - f_excludes.append(exclude.rstrip('/')) - return f_excludes - -def check_excludes(root, excludes): - """ - Check if the directory is in the exclude list. - """ - for exclude in excludes: - if root[:len(exclude)] == exclude: - return True - return False - -def check_py_file(files): - """ - Return a list with only the python scripts (remove all other files). - """ - py_files = [fich for fich in files if fich[-3:] == '.py'] - return py_files - - -if __name__ == '__main__': - - parser = optparse.OptionParser(usage="""usage: %prog [options] [exclude paths, ...] - -Note: By default this script will not overwrite already created files.""") - parser.add_option("-n", "--doc-header", action="store", dest="header", help="Documentation Header (default=Project)", default="Project") - parser.add_option("-d", "--dest-dir", action="store", dest="destdir", help="Output destination directory", default="") - parser.add_option("-s", "--suffix", action="store", dest="suffix", help="module suffix (default=txt)", default="txt") - parser.add_option("-m", "--maxdepth", action="store", dest="maxdepth", help="Maximum depth of submodules to show in the TOC (default=4)", type="int", default=4) - parser.add_option("-r", "--dry-run", action="store_true", dest="dryrun", help="Run the script without creating the files") - parser.add_option("-f", "--force", action="store_true", dest="force", help="Overwrite all the files") - parser.add_option("-t", "--no-toc", action="store_true", dest="notoc", help="Don't create the table of content file") - (opts, args) = parser.parse_args() - if len(args) < 1: - parser.error("package path is required.") - else: - if os.path.isdir(args[0]): - # if there's some exclude arguments, build the list of excludes - excludes = args[1:] - recurse_tree(args[0], excludes, opts) - else: - print '%s is not a valid directory.' % args - - diff --git a/doc/make-doc_html.bat b/doc/make-doc_html.bat deleted file mode 100755 index 87d31b7e..00000000 --- a/doc/make-doc_html.bat +++ /dev/null @@ -1,3 +0,0 @@ -:: run from web2py root folder because of autodoc & web2py import behaviour!!!! -sphinx-build -b html -w doc\sphinx-build.log -Ea doc/source applications/examples/static/sphinx -::sphinx-build -b html -w sphinx-build.log -Ea source ../applications/examples/static/sphinx diff --git a/doc/make-doc_html.sh b/doc/make-doc_html.sh deleted file mode 100755 index 46e6e0ee..00000000 --- a/doc/make-doc_html.sh +++ /dev/null @@ -1,3 +0,0 @@ -# run from web2py root folder because of autodoc & web2py import behaviour!!!! -sphinx-build -b html -w doc/sphinx-build.log -Ea doc/source applications/examples/static/sphinx -#sphinx-build -b html -w sphinx-build.log -Ea source ../applications/examples/static/sphinx diff --git a/doc/make.bat b/doc/make.bat deleted file mode 100755 index 23a62cf5..00000000 --- a/doc/make.bat +++ /dev/null @@ -1,112 +0,0 @@ -@ECHO OFF - -REM Command file for Sphinx documentation - -set SPHINXBUILD=sphinx-build -set ALLSPHINXOPTS=-d build/doctrees %SPHINXOPTS% source -if NOT "%PAPER%" == "" ( - set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% -) - -if "%1" == "" goto help - -if "%1" == "help" ( - :help - echo.Please use `make ^` where ^ is one of - echo. html to make standalone HTML files - echo. dirhtml to make HTML files named index.html in directories - echo. pickle to make pickle files - echo. json to make JSON files - echo. htmlhelp to make HTML files and a HTML help project - echo. qthelp to make HTML files and a qthelp project - echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter - echo. changes to make an overview over all changed/added/deprecated items - echo. linkcheck to check all external links for integrity - echo. doctest to run all doctests embedded in the documentation if enabled - goto end -) - -if "%1" == "clean" ( - for /d %%i in (build\*) do rmdir /q /s %%i - del /q /s build\* - goto end -) - -if "%1" == "html" ( - %SPHINXBUILD% -b html %ALLSPHINXOPTS% build/html - echo. - echo.Build finished. The HTML pages are in build/html. - goto end -) - -if "%1" == "dirhtml" ( - %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% build/dirhtml - echo. - echo.Build finished. The HTML pages are in build/dirhtml. - goto end -) - -if "%1" == "pickle" ( - %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% build/pickle - echo. - echo.Build finished; now you can process the pickle files. - goto end -) - -if "%1" == "json" ( - %SPHINXBUILD% -b json %ALLSPHINXOPTS% build/json - echo. - echo.Build finished; now you can process the JSON files. - goto end -) - -if "%1" == "htmlhelp" ( - %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% build/htmlhelp - echo. - echo.Build finished; now you can run HTML Help Workshop with the ^ -.hhp project file in build/htmlhelp. - goto end -) - -if "%1" == "qthelp" ( - %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% build/qthelp - echo. - echo.Build finished; now you can run "qcollectiongenerator" with the ^ -.qhcp project file in build/qthelp, like this: - echo.^> qcollectiongenerator build\qthelp\Web2Py.qhcp - echo.To view the help file: - echo.^> assistant -collectionFile build\qthelp\Web2Py.ghc - goto end -) - -if "%1" == "latex" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% build/latex - echo. - echo.Build finished; the LaTeX files are in build/latex. - goto end -) - -if "%1" == "changes" ( - %SPHINXBUILD% -b changes %ALLSPHINXOPTS% build/changes - echo. - echo.The overview file is in build/changes. - goto end -) - -if "%1" == "linkcheck" ( - %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% build/linkcheck - echo. - echo.Link check complete; look for any errors in the above output ^ -or in build/linkcheck/output.txt. - goto end -) - -if "%1" == "doctest" ( - %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% build/doctest - echo. - echo.Testing of doctests in the sources finished, look at the ^ -results in build/doctest/output.txt. - goto end -) - -:end diff --git a/doc/problematic_files.rst b/doc/problematic_files.rst deleted file mode 100755 index 9f2f8bac..00000000 --- a/doc/problematic_files.rst +++ /dev/null @@ -1,7 +0,0 @@ -faq -======= - -web2py_DAL_understands_Django_and_SQLAlchemy_models.rst - -docstrings -============= diff --git a/doc/source/_static/pics/logo.png b/doc/source/_static/pics/logo.png deleted file mode 100755 index ec048d7d5555100df1536abc0585841b0e55a196..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41466 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%0AYetYKm>4n`_E@4RQWU7LR89G?@7eJ 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 diff --git a/doc/source/_static/pics/logo_colored.png b/doc/source/_static/pics/logo_colored.png deleted file mode 100755 index ac1e8e5ae7c8ed56a73237c9f32e847d8007a50b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15988 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 diff --git a/doc/source/_static/pics/logo_small.jpg b/doc/source/_static/pics/logo_small.jpg deleted file mode 100755 index c0672f6b571d8519bbe4968b220d4bec72371304..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13421 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 z 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%0A(*W3u za;WG@Ni+-m&wdtu?&nS+;Bz}&l~+c#J8Xzb$p{4xTYkh@Q9meMeSP8|vt)}T;CHd~ z;d7=|I8g86riU|l8quAAdzgR?1oTKSYq9NYbg?Uu_A*H@rcGx&ET%&VkvY0`()H#q zkk%pPErpIOr&!Eh2vJQra3O#EzYQP!Rr`Db{WAo7D2->M{7BJvj8uph>?)x&Z}Ucj zvs%TpEb2g%A=}{6;1FZBPNYJHh}=vNCb8CuX6>oPBfmVy0DDLY9NcvZ%R z7x6p<{xdSQJ9W;adQKE7rmjj!Rf;L1>i3+L%?8eK=i!RP7TVExDq_FJY07yGVnf&k=iPW}QqBCLk*>znNogwIn-RZ0(cDyu-<@U@uxT?J#dj8CNANatj1pE)+U)hVF z_ac<0fs&w83MJo|<{jQ>czlB&C+)-?VBVwcXlha`at7QTpgscF%g}!A{o8gybv=9U zf7-J0lmtGGLu9Z~B(2C&RiTJda?$!N-m2hutDw&=q&W}F#{~Csd!7n9N@BDCjIy~$ zqm45gSbM4fANc+EL2u5cY%>(q8kPdd;t@BytD7+s(PgZjdLWM-toGvAY7w;(iD*OI zR$bibK#Xsd+$`drABB^i8Ru4n@E6{!mDEVsWxTp$q$H{Zl*%5{-F(XFwHu<6S#}*y z3CX5|%qV~a;xQ>{oidrIAZh=A>6+eWy0`9^?9HF_Hhp=r_k+7%^8dfr-2dMHW*O)| zg@6z6wl~8~_eDfe%c@g$glSbRxni5&@>YlMj*6+%XHM0rW6={~LXzYVKxs;bJtk-O zn(lC~$wj-IyuZ`*w4QYG_3cjoR9U>8f<6Ll%V^j=RJmc~iB@ak`2zZ97Wl7u8{seg zT0|<>LcEHFf(S(ewQqQ9TJLT=oI;#s?7tu^x+WIg0!UT5*zWX3+nnBThtucpF}c>b z>1rJ?UG)PdSFMXvaa2n#I^_^mR#;mE-KRoHkY5yJG9$hJvkdi93;4hO>+rFU5uDvp zb`OLgbwLY)6jZ70aQd1hlgsz2FU#T0=c7e$C+^2qeahr{*jW)i+$5GYU+eF3kFmt*a{IA!bPI^=b9(e%XDGPa9rEvXhno{7TMxxF zTbO!FOf|w(1j-;qgO<{2i=YKnJq%o>Dz6pMb5!NG)X{rPBpVRjgz`z0A0l#w7_$o4 zJNlj*82{*pP9drT@Fy1%y$751{g!x6#ades(Nc(Me$O2XUhD646=#|2JSQAIc~68L zrZ>9N8xDTxjW3%y>>ORO_OpsyDabxGIsrteY*~5z`|mmMksF^Edge0l(hiczf)SIH=XmJ}^wDT0=*QYO+GMru}RNXjV}5n~qc{G_==JZwU zTl2704_oQhpoB;<20KNNBB~|TsEksLB5D}w)@swFXhoj*A%0k`9SYfh*ydUdt>6Ek zGF6@lN*c#}N0p74%@>+n#vN}+%QqdUf)Qr-!aZ+ zD{_Uv)!iDL_rAu%W53#bB&Fi%az5BnExLBdi75`5tUW9ld)Q>7r%aE()$RAUI{o!W zoc?-6Qq{CZHBYpXQd<_ZjA}teih`EZQUXefR#dgBmO4fnp|wqMLtn%TYEd=xs}q)D z$+BmU<)Ljyjl7S1;IEkYz#km({@CxlpM!sU@wZ{E~lsUq?2##H2G>%+^VZu zb+P3XQDwk3i$D=5TBV3m1}&@Aii*}ED-Db`qcCiVhaYJehEXeO6!%5!+N)hDQUA6F z7hTmTJ#l#E^%=kQN9_5BKL>c;g8rEYetS}JG_A1Nc{ zSvL4b%87y%fP%^Kn9~@d#a_h`bCtY ziWWsFS*vA1Dyr1fP>YlXMqAA&@C83`BaLd!QWO@)E#rqQ(}&@y12aHhs^-`R`ux|= z=l0A3zdfmVdawGc&kM6n8e*iR$h3%7#wFX_>aK`J{n}|6$vV=a#{r@PrdJBG8B}vuGlBz~XRnW2#N*=c4*{BEZsi;yHSL=~+nvsO9 z&~F5ShGC@=*`OKu`*$h_CNy{EN)5k#=V@(po)xOYt&dafUmv-{7dAb#WRQY^(m~VJ zc+~UhnF zgBDROs%iBe`lSwzO~L;z*NYjk*K_FS6war!I1ui?=AjcIyoL|!S2M!4ZG&A*o|(h zcd@+^ZB`TMR|c#FC;{XkbD4pjfSQ1k2$@irsWOA25J(w-T6(NCiaW>JwN2_#dLIrB zsmWBabwvXJH&2(oK=A+2X!?`VFWRM&42g(L4Yasxm%8`Nl3orI!xyZt{%JXJcJX4^ z!N7@Og@`xps(&rs?6&M?^Lo5lmWV3@R*|r+)J3?)R_E>HD&RkAL3A@()KE z6b&QI2u@;z?3P`v-Z!IjmqTJd%PQ_idvt?6yUeS0!@Uu$ch~LtW@7qHDREtxxGE48 z0g_uF6JgSWCc>FFCy|280+9)%fS`hzZS6q_U0GDl+Sd2%AQaw(kev`C5`72!_AlrG z=m2DM?!M&U0~oI#hkKH-`fQlxJ9aI+Za3Uk zbfLW(ZPZiKuN2Y*k;029NMwLyB1kNm8fqeEpp(c*<|3vDL@hC!K-+pWUE3BuR{G}X zNKw}s-g=w(>5mv493ZSl0f7U4{J`%%JSDiB^Y;G(zD|xAgPxHh000A4Nkllu1U;<-|GoAJABRw(W|$Zr9su(R%Y%v{rbSGJ=*dH1ARK746RC#94s|oVDUA zk%KIhC_&T#+Qxm;)@ptbkzWyz*G?f*d5}5W8^1sEGDg!Pan+5Kg<*;j){H|H<_U&SK-;A0)vsmrh z#e$UFiWWUETVO~>^eKQTf!R+LWClT|L?MDI0JW;NUR~So8CN!CfN`ODa3|ns%-A<@ z*Y7;#z{hhQ=HP#tCe8is1#n`>@u~Dzf4ulT&7`km>9=DuC@0b{f=FS( z%mC?#Ar)%EhjaIpnG&gp6a-5e)SjpTcC~N1h|a_LP?TfE>5&$PM?{ejdnb4qz&7Sh zTyy)Jzz-KTV9GMcTH8?UR74(tvKvA5uklxg06GD35vDzc*^kbGgk-9UOo$wif<`J> z)&ZtfZM()bZXodG$+3z$b+>OQ>IVInE)f6t_fyZYJwNZceV*Xs%^i@d>c9GOYrzSK z-C6lm?pxA`uqKhsl2GOf$pxlVXk%j2bYx37m({83SGC%z((2?$vA@S|G6lc=GO@o8 lIXDIZw7dKBlbzc$?Z07_^Qx0t*AD;y002ovPDHLkV1nRXr$zt( diff --git a/doc/source/_static/rst/external_hint.txt b/doc/source/_static/rst/external_hint.txt deleted file mode 100755 index 910d6ccf..00000000 --- a/doc/source/_static/rst/external_hint.txt +++ /dev/null @@ -1,22 +0,0 @@ - -.. note:: There is an `ongoing discussion - `_, - on whether this part of the *web2py* documents should be - included in the developer documentation. - - This discussion involves: - - * the `AlterEgo (FAQ) `_ - * the `User Wiki `_ - - Until this is resolved, the parts under question will be excluded. - - Nevertheless, these party are still available and can be included in - the Sphinx build by the following steps: - - #. back up the directory ``web2py/doc`` - #. unzip the archive ``external_input.zip`` delivered with the - documentation in the directory - ``web2py/doc``. - Existing files should be overwritten. - #. re-build the documentation diff --git a/doc/source/conf.py b/doc/source/conf.py deleted file mode 100755 index 55c12be3..00000000 --- a/doc/source/conf.py +++ /dev/null @@ -1,251 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Web2Py documentation build configuration file, created by -# sphinx-quickstart on Thu Apr 30 17:10:06 2009. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys, os - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.append(os.path.abspath('.')) -#--- sys.path for web2py_modules -web2py_modules = os.path.join('.', '..', '..') -sys.path.append(os.path.abspath(web2py_modules)) - -#print sys.path - -#from gluon import * - - -##--- sys.path for helper packages -sys.path.extend([ -# - # local extension - os.path.join(os.path.dirname(__file__), '..', 'sphinxext', 'local'), - - # numpy standard doc extensions - os.path.join(os.path.dirname(__file__), '..', 'sphinxext', 'numpydoc'), -# -# # _static files - os.path.join(os.path.dirname(__file__), '_static') -]) -# -# -#import sphinx_tools as st -##--- autogenerate API docs -### Auxilary -#script_path = os.path.abspath( -# os.path.join( -# '..', 'sphinxext', 'local', 'generate_modules_modif.py')) -#dest_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), 'contents', 'lib', 'gluon')) -#print 'dest', dest_dir -#package_dir = os.path.abspath(os.path.join(web2py_modules, 'gluon')) -#print 'package_dir', package_dir -#doc_header = (os.path.split(dest_dir)[-1]).capitalize() -#p = st.autogenerate_package_doc(script_path, dest_dir, -# package_dir, -# doc_header, -# suffix='rst', -# overwrite=True) - -# -- General configuration ----------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'numpydoc'] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'Web2Py' -copyright = u'2009, The web2py developers' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. - -#--- get version - -version_file = open(os.path.join('..', '..', 'VERSION'), 'r') -version_content = version_file.read() -version_str = version_content.split('(')[0].strip() -version_str = version_str.split(' ') -# The short X.Y version. -version = version_str[1] -# The full version, including alpha/beta/rc tags. -release = version_str[1] -if len(version_str) > 2: - release += + ' ' + version_str[2] - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of documents that shouldn't be included in the build. -#unused_docs = [] - -# List of directories, relative to source directory, that shouldn't be searched -# for source files. -exclude_trees = [] - -# The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - - -# -- Options for HTML output --------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. Major themes that come with -# Sphinx are currently 'default' and 'sphinxdoc'. -html_theme = 'default' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -html_logo = '_static/pics/logo_colored_small.png' - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_use_modindex = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = '' - -# Output file base name for HTML help builder. -htmlhelp_basename = 'Web2Pydoc' - - -# -- Options for LaTeX output -------------------------------------------------- - -# The paper size ('letter' or 'a4'). -#latex_paper_size = 'letter' - -# The font size ('10pt', '11pt' or '12pt'). -#latex_font_size = '10pt' - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). -latex_documents = [ - ('index', 'Web2Py.tex', u'Web2Py Documentation', - u'The web2py developers', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# Additional stuff for the LaTeX preamble. -#latex_preamble = '' - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_use_modindex = True - - -# Example configuration for intersphinx: refer to the Python standard library. -#--- Intersphinx -intersphinx_mapping = {'http://docs.python.org/dev': None, - } - -#--- CUSTOM -keep_warnings = True -todo_include_todos = True diff --git a/doc/source/docs_contrib.rst b/doc/source/docs_contrib.rst deleted file mode 100755 index be397c8c..00000000 --- a/doc/source/docs_contrib.rst +++ /dev/null @@ -1,100 +0,0 @@ -********************************** -Introduction for documenting -********************************** - -.. rubric:: Some hints on writing documentation with Sphinx for web2py - -Writing documentation -======================== - -official documentation ----------------------------------- - -* `Sphinx `_ - -Docstrings ------------------------- -* official python standard - * `Docstring Conventions `_ - * `Documenting Python `_ -* numpy standard - * `documentation standard `_ - * `Example file `_ - * `Docstring Template `_ - If you use `Eclipse / Pydev `_ you can define this piece as template. - -Helpers ------------------------- - -Editors -________________________ -* `Emacs: see docutils page `_ -* `Gedit (Linux) `_ -* `Ulipad (Win) `_ - -Others -________________________ - -* creating tables in ReST can be painful. Here is a module that can help:: - - easy_install prettytable - import prettytable as pt - mytable =pt.PrettyTable(["id", "category", "recipie"]) - print mytable # copy & paste this into your ReST document! - mytable_string = mytable.get_string() # or insert this string when - generating automatic documents - - -Building documentation -======================== -Follow these steps: - -#. easy_install -U sphinx -#. built with custom make files for web2py => **Note: we could create a - cross-platform python script for this!** - - #. unix-like: ``sh doc/make-doc_html.sh`` - #. windows: ``doc\make-doc_html.bat`` - - Due to the special manner of the *web2py* import mechanism it requires that - the doc is built from the *web2py* root directory. - -#. the result will written to: ``web2py/applications/examples/static/sphinx`` - (the target directory will be automatically created) -#. inspect any error - #. on the :term:`CLI`: see the errors and warnings floating on - ``stderr``/``stdout`` - #. using the above mentioned make files a log file will be written to - ``web2py/doc/sphinx-build.log`` - -Contributing -======================== - -.. warning:: Please ask on the - `Mailinglist `_ before - commiting or pushing to the repositories. - - So far, it has not been agreed on a proper setup to mutually - edit the documentation and especially how to correct the - docstrings without getting to many :term:`DVCS` conflicts. - -#. branch the web2py Sphinx code:: - - bzr branch lp:~web2py/web2py/web2py-sphinx - cd web2py-sphinx - -#. pull the latest code from web2py Sphinx branch:: - - bzr pull - -#. pull latest web2py development version:: - - bzr pull http://bazaar.launchpad.net/~mdipierro/web2py/devel/ - -#. change and edit the documents or docstrings with your edior - -#. push the changes to the web2py Sphinx branch:: - - bzr push lp:~web2py/web2py/web2py-sphinx - - This requires that you are a member of the `web2py team at Launchpad `_ and registered at Launchpad `with your SSA keys `_. You can find more info on the `Launchpad help page `_ diff --git a/doc/source/faq.rst b/doc/source/faq.rst deleted file mode 100755 index 1ad840a5..00000000 --- a/doc/source/faq.rst +++ /dev/null @@ -1,9 +0,0 @@ -Frequently Asked Questions (FAQ) -================================== - -.. rubric:: The pages from the `AlterEgo `_ - -.. note:: These pages are extracted as plain and not yet converted into - :term:`ReSt` formated documents. - -.. include:: _static/rst/external_hint.txt diff --git a/doc/source/glossary.rst b/doc/source/glossary.rst deleted file mode 100755 index b0466afe..00000000 --- a/doc/source/glossary.rst +++ /dev/null @@ -1,15 +0,0 @@ -*************************** -Glossary -*************************** - -.. glossary:: - :sorted: - - ReSt - ReStructured Text ASCII markup format - - CLI - Command Line Interface - - DVCS - Distributed Version Control System diff --git a/doc/source/gluon/gluon.compat.rst b/doc/source/gluon/gluon.compat.rst deleted file mode 100755 index 6cecb8ce..00000000 --- a/doc/source/gluon/gluon.compat.rst +++ /dev/null @@ -1,13 +0,0 @@ -Compat Documentation -==================== - -This page contains the Compat Package documentation. - -The :mod:`uuid` Module ----------------------- - -.. automodule:: gluon.compat.uuid - :members: - :undoc-members: - :show-inheritance: - diff --git a/doc/source/gluon/gluon.contrib.gateways.rst b/doc/source/gluon/gluon.contrib.gateways.rst deleted file mode 100755 index f78116b8..00000000 --- a/doc/source/gluon/gluon.contrib.gateways.rst +++ /dev/null @@ -1,13 +0,0 @@ -Gateways Documentation -====================== - -This page contains the Gateways Package documentation. - -The :mod:`fcgi` Module ----------------------- - -.. automodule:: gluon.contrib.gateways.fcgi - :members: - :undoc-members: - :show-inheritance: - diff --git a/doc/source/gluon/gluon.contrib.markdown.rst b/doc/source/gluon/gluon.contrib.markdown.rst deleted file mode 100755 index 621efae4..00000000 --- a/doc/source/gluon/gluon.contrib.markdown.rst +++ /dev/null @@ -1,21 +0,0 @@ -Markdown Documentation -====================== - -This page contains the Markdown Package documentation. - -The :mod:`markdown` Package ---------------------------- - -.. automodule:: gluon.contrib.markdown - :members: - :undoc-members: - :show-inheritance: - -The :mod:`markdown2` Module ---------------------------- - -.. automodule:: gluon.contrib.markdown.markdown2 - :members: - :undoc-members: - :show-inheritance: - diff --git a/doc/source/gluon/gluon.contrib.memcache.rst b/doc/source/gluon/gluon.contrib.memcache.rst deleted file mode 100755 index fb3a99a7..00000000 --- a/doc/source/gluon/gluon.contrib.memcache.rst +++ /dev/null @@ -1,21 +0,0 @@ -Memcache Documentation -====================== - -This page contains the Memcache Package documentation. - -The :mod:`memcache` Module --------------------------- - -.. automodule:: gluon.contrib.memcache.memcache - :members: - :undoc-members: - :show-inheritance: - -The :mod:`memcache` Package ---------------------------- - -.. automodule:: gluon.contrib.memcache - :members: - :undoc-members: - :show-inheritance: - diff --git a/doc/source/gluon/gluon.contrib.pyrtf.rst b/doc/source/gluon/gluon.contrib.pyrtf.rst deleted file mode 100755 index 06cce8e2..00000000 --- a/doc/source/gluon/gluon.contrib.pyrtf.rst +++ /dev/null @@ -1,53 +0,0 @@ -Pyrtf Documentation -=================== - -This page contains the Pyrtf Package documentation. - -The :mod:`Elements` Module --------------------------- - -.. automodule:: gluon.contrib.pyrtf.Elements - :members: - :undoc-members: - :show-inheritance: - -The :mod:`Renderer` Module --------------------------- - -.. automodule:: gluon.contrib.pyrtf.Renderer - :members: - :undoc-members: - :show-inheritance: - -The :mod:`PropertySets` Module ------------------------------- - -.. automodule:: gluon.contrib.pyrtf.PropertySets - :members: - :undoc-members: - :show-inheritance: - -The :mod:`pyrtf` Package ------------------------- - -.. automodule:: gluon.contrib.pyrtf - :members: - :undoc-members: - :show-inheritance: - -The :mod:`Constants` Module ---------------------------- - -.. automodule:: gluon.contrib.pyrtf.Constants - :members: - :undoc-members: - :show-inheritance: - -The :mod:`Styles` Module ------------------------- - -.. automodule:: gluon.contrib.pyrtf.Styles - :members: - :undoc-members: - :show-inheritance: - diff --git a/doc/source/gluon/gluon.contrib.rst b/doc/source/gluon/gluon.contrib.rst deleted file mode 100755 index 84a175fb..00000000 --- a/doc/source/gluon/gluon.contrib.rst +++ /dev/null @@ -1,80 +0,0 @@ -Contrib Documentation -===================== - -This page contains the Contrib Package documentation. - -Subpackages ------------ - -.. toctree:: - - gluon.contrib.pyrtf - gluon.contrib.gateways - gluon.contrib.markdown - gluon.contrib.memcache - gluon.contrib.simplejson - -The :mod:`feedparser` Module ----------------------------- - -.. automodule:: gluon.contrib.feedparser - :members: - :undoc-members: - :show-inheritance: - -The :mod:`memdb` Module ------------------------ - -.. automodule:: gluon.contrib.memdb - :members: - :undoc-members: - :show-inheritance: - -The :mod:`rss2` Module ----------------------- - -.. automodule:: gluon.contrib.rss2 - :members: - :undoc-members: - :show-inheritance: - -The :mod:`wsgihooks` Module ---------------------------- - -.. automodule:: gluon.contrib.wsgihooks - :members: - :undoc-members: - :show-inheritance: - -The :mod:`taskbar_widget` Module --------------------------------- - -.. automodule:: gluon.contrib.taskbar_widget - :members: - :undoc-members: - :show-inheritance: - -The :mod:`cron` Module ----------------------- - -.. automodule:: gluon.contrib.cron - :members: - :undoc-members: - :show-inheritance: - -The :mod:`gae_memcache` Module ------------------------------- - -.. automodule:: gluon.contrib.gae_memcache - :members: - :undoc-members: - :show-inheritance: - -The :mod:`gql` Module ---------------------- - -.. automodule:: gluon.contrib.gql - :members: - :undoc-members: - :show-inheritance: - diff --git a/doc/source/gluon/gluon.contrib.simplejson.rst b/doc/source/gluon/gluon.contrib.simplejson.rst deleted file mode 100755 index efb9c029..00000000 --- a/doc/source/gluon/gluon.contrib.simplejson.rst +++ /dev/null @@ -1,37 +0,0 @@ -Simplejson Documentation -======================== - -This page contains the Simplejson Package documentation. - -The :mod:`encoder` Module -------------------------- - -.. automodule:: gluon.contrib.simplejson.encoder - :members: - :undoc-members: - :show-inheritance: - -The :mod:`simplejson` Package ------------------------------ - -.. automodule:: gluon.contrib.simplejson - :members: - :undoc-members: - :show-inheritance: - -The :mod:`scanner` Module -------------------------- - -.. automodule:: gluon.contrib.simplejson.scanner - :members: - :undoc-members: - :show-inheritance: - -The :mod:`decoder` Module -------------------------- - -.. automodule:: gluon.contrib.simplejson.decoder - :members: - :undoc-members: - :show-inheritance: - diff --git a/doc/source/gluon/gluon.rst b/doc/source/gluon/gluon.rst deleted file mode 100755 index 22fcd05c..00000000 --- a/doc/source/gluon/gluon.rst +++ /dev/null @@ -1,220 +0,0 @@ -Gluon Package -=================== - -This page contains the Gluon Package documentation. - -Subpackages ------------ - -.. toctree:: - - gluon.compat - gluon.contrib - -The :mod:`validators` Module ----------------------------- - -.. automodule:: gluon.validators - :members: - :undoc-members: - :show-inheritance: - -The :mod:`sql` Module ---------------------- - -.. automodule:: gluon.sql - :members: - :undoc-members: - :show-inheritance: - -The :mod:`xmlrpc` Module ------------------------- - -.. automodule:: gluon.xmlrpc - :members: - :undoc-members: - :show-inheritance: - -The :mod:`shell` Module ------------------------ - -.. automodule:: gluon.shell - :members: - :undoc-members: - :show-inheritance: - -The :mod:`utils` Module ------------------------ - -.. automodule:: gluon.utils - :members: - :undoc-members: - :show-inheritance: - -The :mod:`globals` Module -------------------------- - -.. automodule:: gluon.globals - :members: - :undoc-members: - :show-inheritance: - -The :mod:`compileapp` Module ----------------------------- - -.. automodule:: gluon.compileapp - :members: - :undoc-members: - :show-inheritance: - -The :mod:`wsgiserver` Module ----------------------------- - -.. automodule:: gluon.wsgiserver - :members: - :undoc-members: - :show-inheritance: - -The :mod:`winservice` Module ----------------------------- - -.. automodule:: gluon.winservice - :members: - :undoc-members: - :show-inheritance: - -The :mod:`template` Module --------------------------- - -.. automodule:: gluon.template - :members: - :undoc-members: - :show-inheritance: - -The :mod:`fileutils` Module ---------------------------- - -.. automodule:: gluon.fileutils - :members: - :undoc-members: - :show-inheritance: - -The :mod:`sqlhtml` Module -------------------------- - -.. automodule:: gluon.sqlhtml - :members: - :undoc-members: - :show-inheritance: - -The :mod:`tools` Module ------------------------ - -.. automodule:: gluon.tools - :members: - :undoc-members: - :show-inheritance: - -The :mod:`languages` Module ---------------------------- - -.. automodule:: gluon.languages - :members: - :undoc-members: - :show-inheritance: - -The :mod:`streamer` Module --------------------------- - -.. automodule:: gluon.streamer - :members: - :undoc-members: - :show-inheritance: - -The :mod:`restricted` Module ----------------------------- - -.. automodule:: gluon.restricted - :members: - :undoc-members: - :show-inheritance: - -The :mod:`http` Module ----------------------- - -.. automodule:: gluon.http - :members: - :undoc-members: - :show-inheritance: - -The :mod:`storage` Module -------------------------- - -.. automodule:: gluon.storage - :members: - :undoc-members: - :show-inheritance: - -The :mod:`highlight` Module ---------------------------- - -.. automodule:: gluon.highlight - :members: - :undoc-members: - :show-inheritance: - -The :mod:`cache` Module ------------------------ - -.. automodule:: gluon.cache - :members: - :undoc-members: - :show-inheritance: - -The :mod:`sanitizer` Module ---------------------------- - -.. automodule:: gluon.sanitizer - :members: - :undoc-members: - :show-inheritance: - -The :mod:`main` Module ----------------------- - -.. automodule:: gluon.main - :members: - :undoc-members: - :show-inheritance: - -The :mod:`widget` Module ------------------------- - -.. automodule:: gluon.widget - :members: - :undoc-members: - :show-inheritance: - -The :mod:`rewrite` Module -------------------------- - -.. automodule:: gluon.rewrite - :members: - :undoc-members: - :show-inheritance: - -The :mod:`html` Module ----------------------- - -.. automodule:: gluon.html - :members: - :undoc-members: - :show-inheritance: - -The :mod:`contenttype` Module ------------------------------ - -.. automodule:: gluon.contenttype - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/source/index.rst b/doc/source/index.rst deleted file mode 100755 index 795027c2..00000000 --- a/doc/source/index.rst +++ /dev/null @@ -1,91 +0,0 @@ -.. Web2Py documentation master file, created by - sphinx-quickstart on Thu Apr 30 17:10:06 2009. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to Web2Py's documentation! -================================== - -.. warning:: This is a BETA version of the Sphinx based documentation for - *web2py*. **It is subject to change!** - -.. note:: The documentation at the current stage is intended for develpers - and contributors. They shall have the possibility to test their - docstrings and markup. - -.. note:: Please read :doc:`docs_contrib` for instructions to Sphinx - documentation writing for *web2py*! - -Contents -=================== - -General Documents -------------------- -.. toctree:: - :maxdepth: 2 - - docs_contrib - docs_overview - web2py_todo - glossary - -Contributed Documents ------------------------- -.. toctree:: - :maxdepth: 1 - - user_wiki - faq - - - -.. User Wiki - ------------------- - - .. rubric:: The pages from the `User Wiki `_ - - .. note:: According to an `ongoing discussion `_, - the page order and structure may be - changed in the future. - - .. on error do:: - - rename 's/\.txt/\.rst/' *.txt - - .. toctree:: - :maxdepth: 2 - :glob: - - user_wiki/* - - -.. Frequently Asked Questions (FAQ) - ---------------------------------- - - .. rubric:: The pages from the `AlterEgo `_ - - .. note:: These pages are extracted as plain and not yet converted into - :term:`ReSt` formated documents. - - .. toctree:: - :maxdepth: 2 - :glob: - - faq/* - -Modules -------------------- - -.. toctree:: - :maxdepth: 2 - - - modules - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/doc/source/modules.rst b/doc/source/modules.rst deleted file mode 100755 index dad3b9ce..00000000 --- a/doc/source/modules.rst +++ /dev/null @@ -1,10 +0,0 @@ -Web2Py Modules -==================== - -.. rubric:: This page contains the Web2Py Modules documentation. - -.. toctree:: - :maxdepth: 5 - - gluon/gluon - diff --git a/doc/source/user_wiki.rst b/doc/source/user_wiki.rst deleted file mode 100755 index 0695fad6..00000000 --- a/doc/source/user_wiki.rst +++ /dev/null @@ -1,6 +0,0 @@ -User Wiki -=================== - -.. rubric:: The pages from the `User Wiki `_ - -.. include:: _static/rst/external_hint.txt diff --git a/doc/source/web2py_todo.rst b/doc/source/web2py_todo.rst deleted file mode 100755 index f3bd98cf..00000000 --- a/doc/source/web2py_todo.rst +++ /dev/null @@ -1,28 +0,0 @@ -*************************** -Todo & Feature Proposals -*************************** - -Documentation -======================== - -#. update or create a .bzrignore -#. correct docstrings -#. add more hand written documentation. -#. customise sphinx theme - #. colors -#. fix long lines -#. decide finally what to do with FAQ and wiki - #. FAQ - #. document API doc and add the script (``generate_modules.py``) to - tools - #. fix FAQ docs - #. User Wiki - #. document wiki markdown to :term`ReSt` conversion and add the script - (``convert_faq.py``)to tools - #. fix ``user_wiki`` docs - -Proposed new features -======================== - -#. new feature x -#. new feature z diff --git a/doc/sphinxext/local/generate_modules.py b/doc/sphinxext/local/generate_modules.py deleted file mode 100755 index ecbe9d9a..00000000 --- a/doc/sphinxext/local/generate_modules.py +++ /dev/null @@ -1,258 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Sropulpof -# Copyright (C) 2008 Société des arts technologiques (SAT) -# http://www.sat.qc.ca -# All rights reserved. -# -# This file is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# Sropulpof is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Sropulpof. If not, see . - -""" -This script parse a directory tree looking for python modules and packages and -create ReST files appropriately to create code documentation with Sphinx. -It also create a modules index. -""" - -import os -import optparse - - -# automodule options -options = ['members', - 'undoc-members', -# 'inherited-members', # disable because there's a bug in sphinx - 'show-inheritance'] - -def create_file_name(base, opts): - """Create file name from base name, path and suffix""" - return os.path.join(opts.destdir, "%s.%s" % (base, opts.suffix)) - -def write_directive(module): - """Create the automodule directive and add the options""" - directive = '.. automodule:: %s\n' % module - for option in options: - directive += ' :%s:\n' % option - return directive - -def write_heading(module, kind='Module'): - """Create the page heading.""" - module = module.title() - heading = title_line(module + ' Documentation', '=') - heading += 'This page contains the %s %s documentation.\n\n' % (module, kind) - return heading - -def write_sub(module, kind='Module'): - """Create the module subtitle""" - sub = title_line('The :mod:`%s` %s' % (module, kind), '-') - return sub - -def title_line(title, char): - """ Underline the title with the character pass, with the right length.""" - return '%s\n%s\n\n' % (title, len(title) * char) - -def create_module_file(root, module, opts): - """Build the text of the file and write the file.""" - name = create_file_name(module, opts) - if not opts.force and os.path.isfile(name): - print 'File %s already exists.' % name - elif check_for_code('%s/%s.py' % (root, module)): # don't build the file if there's no code in it - print 'Creating file %s for module.' % name - text = write_heading(module) - text += write_sub(module) - text += write_directive(module) - - # write the file - if not opts.dryrun: - fd = open(name, 'w') - fd.write(text) - fd.close() - -def create_package_file(root, subroot, py_files, opts, subs=None): - """Build the text of the file and write the file.""" - package = root.rpartition('/')[2].lower() - name = create_file_name(subroot, opts) - if not opts.force and os.path.isfile(name): - print 'File %s already exists.' % name - else: - print 'Creating file %s for package.' % name - text = write_heading(package, 'Package') - if subs == None: - subs = [] - else: - # build a list of directories that are package (they contain an __init_.py file) - subs = [sub for sub in subs if os.path.isfile('%s/%s/__init__.py' % (root, sub))] - # if there's some package directories, add a TOC for theses subpackages - if subs: - text += title_line('Subpackages', '-') - text += '.. toctree::\n\n' - for sub in subs: - text += ' %s.%s\n' % (subroot, sub) - text += '\n' - - # add each package's module - for py_file in py_files: - if not check_for_code('%s/%s' % (root, py_file)): - # don't build the file if there's no code in it - continue - py_file = py_file[:-3] - py_path = '%s.%s' % (subroot, py_file) - kind = "Module" - if py_file == '__init__': - kind = "Package" - text += write_sub(kind == 'Package' and package or py_file, kind) - text += write_directive(kind == "Package" and subroot or py_path) - text += '\n' - - # write the file - if not opts.dryrun: - fd = open(name, 'w') - fd.write(text) - fd.close() - -def check_for_code(module): - """ - Check if there's at least one class or one function in the module. - """ - fd = open(module, 'r') - for line in fd: - if line.startswith('def ') or line.startswith('class '): - fd.close() - return True - fd.close() - return False - -def recurse_tree(path, excludes, opts): - """ - Look for every file in the directory tree and create the corresponding - ReST files. - """ - toc = [] - excludes = format_excludes(path, excludes) - tree = os.walk(path, False) - for root, subs, files in tree: - # keep only the Python script files - py_files = check_py_file(files) - # remove hidden ('.') and private ('_') directories - subs = [sub for sub in subs if sub[0] not in ['.', '_']] - # check if there's valid files to process - if "/." in root or "/_" in root \ - or not py_files \ - or check_excludes(root, excludes): - continue - subroot = root[len(path):].lstrip('/').replace('/', '.') - if root == path: - # we are at the root level so we create only modules - for py_file in py_files: - module = py_file[:-3] - create_module_file(root, module, opts) - toc.append(module) - elif not subs and "__init__.py" in py_files: - # we are in a package without sub package - create_package_file(root, subroot, py_files, opts=opts) - toc.append(subroot) - elif "__init__.py" in py_files: - # we are in package with subpackage(s) - create_package_file(root, subroot, py_files, opts, subs) - toc.append(subroot) - - # create the module's index - if not opts.notoc: - modules_toc(toc, opts) - -def modules_toc(modules, opts, name='modules'): - """ - Create the module's index. - """ - fname = create_file_name(name, opts) - if not opts.force and os.path.exists(fname): - print "File %s already exists." % name - return - - print "Creating module's index modules.txt." - text = write_heading(opts.header, 'Modules') - text += title_line('Modules:', '-') - text += '.. toctree::\n' - text += ' :maxdepth: %s\n\n' % opts.maxdepth - - modules.sort() - prev_module = '' - for module in modules: - # look if the module is a subpackage and, if yes, ignore it - if module.startswith(prev_module + '.'): - continue - prev_module = module - text += ' %s\n' % module - - # write the file - if not opts.dryrun: - fd = open(fname, 'w') - fd.write(text) - fd.close() - -def format_excludes(path, excludes): - """ - Format the excluded directory list. - (verify that the path is not from the root of the volume or the root of the - package) - """ - f_excludes = [] - for exclude in excludes: - if exclude[0] != '/' and exclude[:len(path)] != path: - exclude = '%s/%s' % (path, exclude) - # remove trailing slash - f_excludes.append(exclude.rstrip('/')) - return f_excludes - -def check_excludes(root, excludes): - """ - Check if the directory is in the exclude list. - """ - for exclude in excludes: - if root[:len(exclude)] == exclude: - return True - return False - -def check_py_file(files): - """ - Return a list with only the python scripts (remove all other files). - """ - py_files = [fich for fich in files if fich[-3:] == '.py'] - return py_files - - -if __name__ == '__main__': - - parser = optparse.OptionParser(usage="""usage: %prog [options] [exclude paths, ...] - -Note: By default this script will not overwrite already created files.""") - parser.add_option("-n", "--doc-header", action="store", dest="header", help="Documentation Header (default=Project)", default="Project") - parser.add_option("-d", "--dest-dir", action="store", dest="destdir", help="Output destination directory", default="") - parser.add_option("-s", "--suffix", action="store", dest="suffix", help="module suffix (default=txt)", default="txt") - parser.add_option("-m", "--maxdepth", action="store", dest="maxdepth", help="Maximum depth of submodules to show in the TOC (default=4)", type="int", default=4) - parser.add_option("-r", "--dry-run", action="store_true", dest="dryrun", help="Run the script without creating the files") - parser.add_option("-f", "--force", action="store_true", dest="force", help="Overwrite all the files") - parser.add_option("-t", "--no-toc", action="store_true", dest="notoc", help="Don't create the table of content file") - (opts, args) = parser.parse_args() - if len(args) < 1: - parser.error("package path is required.") - else: - if os.path.isdir(args[0]): - # if there's some exclude arguments, build the list of excludes - excludes = args[1:] - recurse_tree(args[0], excludes, opts) - else: - print '%s is not a valid directory.' % args - - diff --git a/doc/sphinxext/local/generate_modules_modif.py b/doc/sphinxext/local/generate_modules_modif.py deleted file mode 100755 index 49268c8f..00000000 --- a/doc/sphinxext/local/generate_modules_modif.py +++ /dev/null @@ -1,271 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Sropulpof -# Copyright (C) 2008 Société des arts technologiques (SAT) -# http://www.sat.qc.ca -# All rights reserved. -# -# This file is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# Sropulpof is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Sropulpof. If not, see . - -""" -This script parse a directory tree looking for python modules and packages and -create ReST files appropriately to create code documentation with Sphinx. -It also create a modules index. -""" - -import os -import optparse - - -# automodule options -options = ['members', - 'undoc-members', -# 'inherited-members', # disable because there's a bug in sphinx - 'show-inheritance'] - -def create_file_name(base, opts): - """Create file name from base name, path and suffix""" - return os.path.join(opts.destdir, "%s.%s" % (base, opts.suffix)) - -def write_directive(package, module): - """Create the automodule directive and add the options""" - directive = '.. automodule:: %s.%s\n' % (package, module) - for option in options: - directive += ' :%s:\n' % option - return directive - -def write_heading(module, kind='Module'): - """Create the page heading.""" - module = module.title() - heading = title_line(module + ' Documentation', '=') - heading += 'This page contains the %s %s documentation.\n\n' % (module, kind) - return heading - -def write_sub(module, kind='Module'): - """Create the module subtitle""" - sub = title_line('The :mod:`%s` %s' % (module, kind), '-') - return sub - -def title_line(title, char): - """ Underline the title with the character pass, with the right length.""" - return '%s\n%s\n\n' % (title, len(title) * char) - -def create_module_file(root, package, module, opts): - """Build the text of the file and write the file.""" - name = create_file_name(module, opts) - if not opts.force and os.path.isfile(name): - print 'File %s already exists.' % name - elif check_for_code('%s/%s.py' % (root, module)): # don't build the file if there's no code in it - print 'Creating file %s for module.' % name - text = write_heading(module) - text += write_sub(module) - text += write_directive(package, module) - - # write the file - if not opts.dryrun: - fd = open(name, 'w') - fd.write(text) - fd.close() - -def create_package_file(root, subroot, py_files, opts, subs=None): - """Build the text of the file and write the file.""" - package = root.rpartition('/')[2].lower() - name = create_file_name(subroot, opts) - if not opts.force and os.path.isfile(name): - print 'File %s already exists.' % name - else: - print 'Creating file %s for package.' % name - text = write_heading(package, 'Package') - if subs == None: - subs = [] - else: - # build a list of directories that are package (they contain an __init_.py file) - subs = [sub for sub in subs if os.path.isfile('%s/%s/__init__.py' % (root, sub))] - # if there's some package directories, add a TOC for theses subpackages - if subs: - text += title_line('Subpackages', '-') - text += '.. toctree::\n\n' - for sub in subs: - text += ' %s.%s\n' % (subroot, sub) - text += '\n' - - # add each package's module - for py_file in py_files: - if not check_for_code('%s/%s' % (root, py_file)): - # don't build the file if there's no code in it - continue - py_file = py_file[:-3] - py_path = '%s.%s' % (subroot, py_file) - kind = "Module" - if py_file == '__init__': - kind = "Package" - text += write_sub(kind == 'Package' and package or py_file, kind) - text += write_directive(kind == "Package" and subroot or py_path) - text += '\n' - - # write the file - if not opts.dryrun: - fd = open(name, 'w') - fd.write(text) - fd.close() - -def check_for_code(module): - """ - Check if there's at least one class or one function in the module. - """ - fd = open(module, 'r') - for line in fd: - if line.startswith('def ') or line.startswith('class '): - fd.close() - return True - fd.close() - return False - -def recurse_tree(path, excludes, opts): - """ - Look for every file in the directory tree and create the corresponding - ReST files. - """ - package_name = os.path.split(path)[-1] - print 'package name', package_name - toc = [] - excludes = format_excludes(path, excludes) - tree = os.walk(path, False) - for root, subs, files in tree: - # keep only the Python script files - py_files = check_py_file(files) - # remove hidden ('.') and private ('_') directories - subs = [sub for sub in subs if sub[0] not in ['.', '_']] - # check if there's valid files to process - if "/." in root or "/_" in root \ - or not py_files \ - or check_excludes(root, excludes): - continue - subroot = root[len(path):].lstrip('/').replace('/', '.') - if root == path: - # we are at the root level so we create only modules - for py_file in py_files: - module = py_file[:-3] - create_module_file(root, package_name, module, opts) - if not check_for_code(os.path.join(path, module+'.py')): - # don't build the file if there's no code in it - pass - else: - toc.append(module) - elif not subs and "__init__.py" in py_files: - # we are in a package without sub package - create_package_file(root, subroot, py_files, opts=opts) - # FIXME: HERE THE __init__.py should go into the toc only if it contains - # code! - if not check_for_code(subroot): - # don't build the file if there's no code in it - continue - toc.append(subroot) - print 'here' - elif "__init__.py" in py_files: - # we are in package with subpackage(s) - create_package_file(root, subroot, py_files, opts, subs) - toc.append(subroot) - print 'hello' - - # create the module's index - if not opts.notoc: - modules_toc(toc, opts) - -def modules_toc(modules, opts, name='modules'): - """ - Create the module's index. - """ - fname = create_file_name(name, opts) - if not opts.force and os.path.exists(fname): - print "File %s already exists." % name - return - - print "Creating module's index modules.txt." - text = write_heading(opts.header, 'Modules') - text += title_line('Modules:', '-') - text += '.. toctree::\n' - text += ' :maxdepth: %s\n\n' % opts.maxdepth - - modules.sort() - prev_module = '' - for module in modules: - # look if the module is a subpackage and, if yes, ignore it - if module.startswith(prev_module + '.'): - continue - prev_module = module - text += ' %s\n' % module - - # write the file - if not opts.dryrun: - fd = open(fname, 'w') - fd.write(text) - fd.close() - -def format_excludes(path, excludes): - """ - Format the excluded directory list. - (verify that the path is not from the root of the volume or the root of the - package) - """ - f_excludes = [] - for exclude in excludes: - if exclude[0] != '/' and exclude[:len(path)] != path: - exclude = '%s/%s' % (path, exclude) - # remove trailing slash - f_excludes.append(exclude.rstrip('/')) - return f_excludes - -def check_excludes(root, excludes): - """ - Check if the directory is in the exclude list. - """ - for exclude in excludes: - if root[:len(exclude)] == exclude: - return True - return False - -def check_py_file(files): - """ - Return a list with only the python scripts (remove all other files). - """ - py_files = [fich for fich in files if fich[-3:] == '.py'] - return py_files - - -if __name__ == '__main__': - - parser = optparse.OptionParser(usage="""usage: %prog [options] [exclude paths, ...] - -Note: By default this script will not overwrite already created files.""") - parser.add_option("-n", "--doc-header", action="store", dest="header", help="Documentation Header (default=Project)", default="Project") - parser.add_option("-d", "--dest-dir", action="store", dest="destdir", help="Output destination directory", default="") - parser.add_option("-s", "--suffix", action="store", dest="suffix", help="module suffix (default=txt)", default="txt") - parser.add_option("-m", "--maxdepth", action="store", dest="maxdepth", help="Maximum depth of submodules to show in the TOC (default=4)", type="int", default=4) - parser.add_option("-r", "--dry-run", action="store_true", dest="dryrun", help="Run the script without creating the files") - parser.add_option("-f", "--force", action="store_true", dest="force", help="Overwrite all the files") - parser.add_option("-t", "--no-toc", action="store_true", dest="notoc", help="Don't create the table of content file") - (opts, args) = parser.parse_args() - if len(args) < 1: - parser.error("package path is required.") - else: - if os.path.isdir(args[0]): - # if there's some exclude arguments, build the list of excludes - excludes = args[1:] - recurse_tree(args[0], excludes, opts) - else: - print '%s is not a valid directory.' % args - - diff --git a/doc/sphinxext/local/sphinx_tools.py b/doc/sphinxext/local/sphinx_tools.py deleted file mode 100755 index e9f8194d..00000000 --- a/doc/sphinxext/local/sphinx_tools.py +++ /dev/null @@ -1,87 +0,0 @@ -import os -import subprocess -import codecs - - -#--- BZR: changelog information -def write_changelog_bzr(repo_path, output_dir, - output_file='bzr_revision_log.txt', - target_encoding='utf-8'): - """Write the bzr changelog to a file which can then be included in the documentation - """ - - bzr_logfile_path = os.path.join(output_dir, output_file) - bzr_logfile = codecs.open(bzr_logfile_path, 'w', encoding=target_encoding) - try: - p_log = subprocess.Popen(('bzr log --short'), - stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=-1) - (stdout, stderr) = p_log.communicate() - bzr_logfile.write(stdout) - finally: - bzr_logfile.close() - #UnicodeDecodeError: 'ascii' codec can't decode byte 0x81 in position 2871: ordinal not in range(128) - - # like bzr version-info --format python > vers_test.py - - - -#--- BZR: version info - -def write_version_info_bzr(repo_path, output_dir, output_file='_version.py'): - """Write the version information from BZR repository into a version file. - - Parameters - ---------- - repo_path : string - Path to the BZR repository root - repo_path : string - Path to the output directory where the version info is saved - detail, e.g. ``(N,) ndarray`` or ``array_like``. - output_file : string - output file name - - Returns - ------- - p_info : subprocess_obj - contents of the `func:`suprocess.Popen` returns - - """ - bzr_version_filepath = os.path.join(output_dir, output_file) - bzr_version_file = open(bzr_version_filepath, 'w') - p_info = subprocess.Popen(('bzr version-info --format python'), - stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=-1) - (stdout, stderr) = p_info.communicate() - bzr_version_file.write(stdout) - bzr_version_file.close() - - return p_info - - -#--- auto generate documentation - -def autogenerate_package_doc(script_path, dest_dir, - package_dir, - doc_header, - suffix='rst', - overwrite=False): - """Autogenerate package API ReSt documents - - """ - print script_path - if overwrite: - force = '--force' - p_apidoc = subprocess.Popen(('python', script_path, - '--dest-dir='+dest_dir, - '--suffix='+suffix, - '--doc-header='+doc_header, - force, - package_dir), bufsize=-1) - 'sphinxext\local\generate_modules_modif.py --dest-dir=source\contents\lib\auxilary\generated --suffix=rst --force --doc-header=Auxilary ..\..\modules_local\auxilary' - - return p_apidoc - - -if __name__ == "__main__": - repo_path = os.path.join('..', '.') - output_dir = os.path.join('.') - write_changelog_bzr(repo_path, output_dir, output_file='changelog.txt') diff --git a/doc/sphinxext/numpydoc/LICENSE.txt b/doc/sphinxext/numpydoc/LICENSE.txt deleted file mode 100755 index e00efc31..00000000 --- a/doc/sphinxext/numpydoc/LICENSE.txt +++ /dev/null @@ -1,97 +0,0 @@ -------------------------------------------------------------------------------- - The files - - numpydoc.py - - autosummary.py - - autosummary_generate.py - - docscrape.py - - docscrape_sphinx.py - - phantom_import.py - have the following license: - -Copyright (C) 2008 Stefan van der Walt , Pauli Virtanen - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -------------------------------------------------------------------------------- - The files - - compiler_unparse.py - - comment_eater.py - - traitsdoc.py - have the following license: - -This software is OSI Certified Open Source Software. -OSI Certified is a certification mark of the Open Source Initiative. - -Copyright (c) 2006, Enthought, Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of Enthought, Inc. nor the names of its contributors may - be used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------------------- - The files - - only_directives.py - - plot_directive.py - originate from Matplotlib (http://matplotlib.sf.net/) which has - the following license: - -Copyright (c) 2002-2008 John D. Hunter; All Rights Reserved. - -1. This LICENSE AGREEMENT is between John D. Hunter (“JDH”), and the Individual or Organization (“Licensee”) accessing and otherwise using matplotlib software in source or binary form and its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, JDH hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use matplotlib 0.98.3 alone or in any derivative version, provided, however, that JDH’s License Agreement and JDH’s notice of copyright, i.e., “Copyright (c) 2002-2008 John D. Hunter; All Rights Reserved” are retained in matplotlib 0.98.3 alone or in any derivative version prepared by Licensee. - -3. In the event Licensee prepares a derivative work that is based on or incorporates matplotlib 0.98.3 or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to matplotlib 0.98.3. - -4. JDH is making matplotlib 0.98.3 available to Licensee on an “AS IS” basis. JDH MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, JDH MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF MATPLOTLIB 0.98.3 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. - -5. JDH SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF MATPLOTLIB 0.98.3 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING MATPLOTLIB 0.98.3, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material breach of its terms and conditions. - -7. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between JDH and Licensee. This License Agreement does not grant permission to use JDH trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party. - -8. By copying, installing or otherwise using matplotlib 0.98.3, Licensee agrees to be bound by the terms and conditions of this License Agreement. - diff --git a/doc/sphinxext/numpydoc/MANIFEST.in b/doc/sphinxext/numpydoc/MANIFEST.in deleted file mode 100755 index f88ed785..00000000 --- a/doc/sphinxext/numpydoc/MANIFEST.in +++ /dev/null @@ -1,2 +0,0 @@ -recursive-include tests *.py -include *.txt diff --git a/doc/sphinxext/numpydoc/__init__.py b/doc/sphinxext/numpydoc/__init__.py deleted file mode 100755 index ae9073bc..00000000 --- a/doc/sphinxext/numpydoc/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from numpydoc import setup diff --git a/doc/sphinxext/numpydoc/autosummary.py b/doc/sphinxext/numpydoc/autosummary.py deleted file mode 100755 index 2f8a00a3..00000000 --- a/doc/sphinxext/numpydoc/autosummary.py +++ /dev/null @@ -1,349 +0,0 @@ -""" -=========== -autosummary -=========== - -Sphinx extension that adds an autosummary:: directive, which can be -used to generate function/method/attribute/etc. summary lists, similar -to those output eg. by Epydoc and other API doc generation tools. - -An :autolink: role is also provided. - -autosummary directive ---------------------- - -The autosummary directive has the form:: - - .. autosummary:: - :nosignatures: - :toctree: generated/ - - module.function_1 - module.function_2 - ... - -and it generates an output table (containing signatures, optionally) - - ======================== ============================================= - module.function_1(args) Summary line from the docstring of function_1 - module.function_2(args) Summary line from the docstring - ... - ======================== ============================================= - -If the :toctree: option is specified, files matching the function names -are inserted to the toctree with the given prefix: - - generated/module.function_1 - generated/module.function_2 - ... - -Note: The file names contain the module:: or currentmodule:: prefixes. - -.. seealso:: autosummary_generate.py - - -autolink role -------------- - -The autolink role functions as ``:obj:`` when the name referred can be -resolved to a Python object, and otherwise it becomes simple emphasis. -This can be used as the default role to make links 'smart'. - -""" -import sys, os, posixpath, re - -from docutils.parsers.rst import directives -from docutils.statemachine import ViewList -from docutils import nodes - -import sphinx.addnodes, sphinx.roles -from sphinx.util import patfilter - -from docscrape_sphinx import get_doc_object - -import warnings -warnings.warn( - "The numpydoc.autosummary extension can also be found as " - "sphinx.ext.autosummary in Sphinx >= 0.6, and the version in " - "Sphinx >= 0.7 is superior to the one in numpydoc. This numpydoc " - "version of autosummary is no longer maintained.", - DeprecationWarning, stacklevel=2) - -def setup(app): - app.add_directive('autosummary', autosummary_directive, True, (0, 0, False), - toctree=directives.unchanged, - nosignatures=directives.flag) - app.add_role('autolink', autolink_role) - - app.add_node(autosummary_toc, - html=(autosummary_toc_visit_html, autosummary_toc_depart_noop), - latex=(autosummary_toc_visit_latex, autosummary_toc_depart_noop)) - app.connect('doctree-read', process_autosummary_toc) - -#------------------------------------------------------------------------------ -# autosummary_toc node -#------------------------------------------------------------------------------ - -class autosummary_toc(nodes.comment): - pass - -def process_autosummary_toc(app, doctree): - """ - Insert items described in autosummary:: to the TOC tree, but do - not generate the toctree:: list. - - """ - env = app.builder.env - crawled = {} - def crawl_toc(node, depth=1): - crawled[node] = True - for j, subnode in enumerate(node): - try: - if (isinstance(subnode, autosummary_toc) - and isinstance(subnode[0], sphinx.addnodes.toctree)): - env.note_toctree(env.docname, subnode[0]) - continue - except IndexError: - continue - if not isinstance(subnode, nodes.section): - continue - if subnode not in crawled: - crawl_toc(subnode, depth+1) - crawl_toc(doctree) - -def autosummary_toc_visit_html(self, node): - """Hide autosummary toctree list in HTML output""" - raise nodes.SkipNode - -def autosummary_toc_visit_latex(self, node): - """Show autosummary toctree (= put the referenced pages here) in Latex""" - pass - -def autosummary_toc_depart_noop(self, node): - pass - -#------------------------------------------------------------------------------ -# .. autosummary:: -#------------------------------------------------------------------------------ - -def autosummary_directive(dirname, arguments, options, content, lineno, - content_offset, block_text, state, state_machine): - """ - Pretty table containing short signatures and summaries of functions etc. - - autosummary also generates a (hidden) toctree:: node. - - """ - - names = [] - names += [x.strip().split()[0] for x in content - if x.strip() and re.search(r'^[a-zA-Z_]', x.strip()[0])] - - table, warnings, real_names = get_autosummary(names, state, - 'nosignatures' in options) - node = table - - env = state.document.settings.env - suffix = env.config.source_suffix - all_docnames = env.found_docs.copy() - dirname = posixpath.dirname(env.docname) - - if 'toctree' in options: - tree_prefix = options['toctree'].strip() - docnames = [] - for name in names: - name = real_names.get(name, name) - - docname = tree_prefix + name - if docname.endswith(suffix): - docname = docname[:-len(suffix)] - docname = posixpath.normpath(posixpath.join(dirname, docname)) - if docname not in env.found_docs: - warnings.append(state.document.reporter.warning( - 'toctree references unknown document %r' % docname, - line=lineno)) - docnames.append(docname) - - tocnode = sphinx.addnodes.toctree() - tocnode['includefiles'] = docnames - tocnode['maxdepth'] = -1 - tocnode['glob'] = None - tocnode['entries'] = [(None, docname) for docname in docnames] - - tocnode = autosummary_toc('', '', tocnode) - return warnings + [node] + [tocnode] - else: - return warnings + [node] - -def get_autosummary(names, state, no_signatures=False): - """ - Generate a proper table node for autosummary:: directive. - - Parameters - ---------- - names : list of str - Names of Python objects to be imported and added to the table. - document : document - Docutils document object - - """ - document = state.document - - real_names = {} - warnings = [] - - prefixes = [''] - prefixes.insert(0, document.settings.env.currmodule) - - table = nodes.table('') - group = nodes.tgroup('', cols=2) - table.append(group) - group.append(nodes.colspec('', colwidth=10)) - group.append(nodes.colspec('', colwidth=90)) - body = nodes.tbody('') - group.append(body) - - def append_row(*column_texts): - row = nodes.row('') - for text in column_texts: - node = nodes.paragraph('') - vl = ViewList() - vl.append(text, '') - state.nested_parse(vl, 0, node) - try: - if isinstance(node[0], nodes.paragraph): - node = node[0] - except IndexError: - pass - row.append(nodes.entry('', node)) - body.append(row) - - for name in names: - try: - obj, real_name = import_by_name(name, prefixes=prefixes) - except ImportError: - warnings.append(document.reporter.warning( - 'failed to import %s' % name)) - append_row(":obj:`%s`" % name, "") - continue - - real_names[name] = real_name - - doc = get_doc_object(obj) - - if doc['Summary']: - title = " ".join(doc['Summary']) - else: - title = "" - - col1 = u":obj:`%s <%s>`" % (name, real_name) - if doc['Signature']: - sig = re.sub('^[^(\[]*', '', doc['Signature'].strip()) - if '=' in sig: - # abbreviate optional arguments - sig = re.sub(r', ([a-zA-Z0-9_]+)=', r'[, \1=', sig, count=1) - sig = re.sub(r'\(([a-zA-Z0-9_]+)=', r'([\1=', sig, count=1) - sig = re.sub(r'=[^,)]+,', ',', sig) - sig = re.sub(r'=[^,)]+\)$', '])', sig) - # shorten long strings - sig = re.sub(r'(\[.{16,16}[^,]*?),.*?\]\)', r'\1, ...])', sig) - else: - sig = re.sub(r'(\(.{16,16}[^,]*?),.*?\)', r'\1, ...)', sig) - # make signature contain non-breaking spaces - col1 += u"\\ \u00a0" + unicode(sig).replace(u" ", u"\u00a0") - col2 = title - append_row(col1, col2) - - return table, warnings, real_names - -def import_by_name(name, prefixes=[None]): - """ - Import a Python object that has the given name, under one of the prefixes. - - Parameters - ---------- - name : str - Name of a Python object, eg. 'numpy.ndarray.view' - prefixes : list of (str or None), optional - Prefixes to prepend to the name (None implies no prefix). - The first prefixed name that results to successful import is used. - - Returns - ------- - obj - The imported object - name - Name of the imported object (useful if `prefixes` was used) - - """ - for prefix in prefixes: - try: - if prefix: - prefixed_name = '.'.join([prefix, name]) - else: - prefixed_name = name - return _import_by_name(prefixed_name), prefixed_name - except ImportError: - pass - raise ImportError - -def _import_by_name(name): - """Import a Python object given its full name""" - try: - # try first interpret `name` as MODNAME.OBJ - name_parts = name.split('.') - try: - modname = '.'.join(name_parts[:-1]) - __import__(modname) - return getattr(sys.modules[modname], name_parts[-1]) - except (ImportError, IndexError, AttributeError): - pass - - # ... then as MODNAME, MODNAME.OBJ1, MODNAME.OBJ1.OBJ2, ... - last_j = 0 - modname = None - for j in reversed(range(1, len(name_parts)+1)): - last_j = j - modname = '.'.join(name_parts[:j]) - try: - __import__(modname) - except ImportError: - continue - if modname in sys.modules: - break - - if last_j < len(name_parts): - obj = sys.modules[modname] - for obj_name in name_parts[last_j:]: - obj = getattr(obj, obj_name) - return obj - else: - return sys.modules[modname] - except (ValueError, ImportError, AttributeError, KeyError), e: - raise ImportError(e) - -#------------------------------------------------------------------------------ -# :autolink: (smart default role) -#------------------------------------------------------------------------------ - -def autolink_role(typ, rawtext, etext, lineno, inliner, - options={}, content=[]): - """ - Smart linking role. - - Expands to ":obj:`text`" if `text` is an object that can be imported; - otherwise expands to "*text*". - """ - r = sphinx.roles.xfileref_role('obj', rawtext, etext, lineno, inliner, - options, content) - pnode = r[0][0] - - prefixes = [None] - #prefixes.insert(0, inliner.document.settings.env.currmodule) - try: - obj, name = import_by_name(pnode['reftarget'], prefixes) - except ImportError: - content = pnode[0] - r[0][0] = nodes.emphasis(rawtext, content[0].astext(), - classes=content['classes']) - return r diff --git a/doc/sphinxext/numpydoc/autosummary_generate.py b/doc/sphinxext/numpydoc/autosummary_generate.py deleted file mode 100755 index a3270674..00000000 --- a/doc/sphinxext/numpydoc/autosummary_generate.py +++ /dev/null @@ -1,219 +0,0 @@ -#!/usr/bin/env python -r""" -autosummary_generate.py OPTIONS FILES - -Generate automatic RST source files for items referred to in -autosummary:: directives. - -Each generated RST file contains a single auto*:: directive which -extracts the docstring of the referred item. - -Example Makefile rule:: - - generate: - ./ext/autosummary_generate.py -o source/generated source/*.rst - -""" -import glob, re, inspect, os, optparse, pydoc -from autosummary import import_by_name - -try: - from phantom_import import import_phantom_module -except ImportError: - import_phantom_module = lambda x: x - -def main(): - p = optparse.OptionParser(__doc__.strip()) - p.add_option("-p", "--phantom", action="store", type="string", - dest="phantom", default=None, - help="Phantom import modules from a file") - p.add_option("-o", "--output-dir", action="store", type="string", - dest="output_dir", default=None, - help=("Write all output files to the given directory (instead " - "of writing them as specified in the autosummary:: " - "directives)")) - options, args = p.parse_args() - - if len(args) == 0: - p.error("wrong number of arguments") - - if options.phantom and os.path.isfile(options.phantom): - import_phantom_module(options.phantom) - - # read - names = {} - for name, loc in get_documented(args).items(): - for (filename, sec_title, keyword, toctree) in loc: - if toctree is not None: - path = os.path.join(os.path.dirname(filename), toctree) - names[name] = os.path.abspath(path) - - # write - for name, path in sorted(names.items()): - if options.output_dir is not None: - path = options.output_dir - - if not os.path.isdir(path): - os.makedirs(path) - - try: - obj, name = import_by_name(name) - except ImportError, e: - print "Failed to import '%s': %s" % (name, e) - continue - - fn = os.path.join(path, '%s.rst' % name) - - if os.path.exists(fn): - # skip - continue - - f = open(fn, 'w') - - try: - f.write('%s\n%s\n\n' % (name, '='*len(name))) - - if inspect.isclass(obj): - if issubclass(obj, Exception): - f.write(format_modulemember(name, 'autoexception')) - else: - f.write(format_modulemember(name, 'autoclass')) - elif inspect.ismodule(obj): - f.write(format_modulemember(name, 'automodule')) - elif inspect.ismethod(obj) or inspect.ismethoddescriptor(obj): - f.write(format_classmember(name, 'automethod')) - elif callable(obj): - f.write(format_modulemember(name, 'autofunction')) - elif hasattr(obj, '__get__'): - f.write(format_classmember(name, 'autoattribute')) - else: - f.write(format_modulemember(name, 'autofunction')) - finally: - f.close() - -def format_modulemember(name, directive): - parts = name.split('.') - mod, name = '.'.join(parts[:-1]), parts[-1] - return ".. currentmodule:: %s\n\n.. %s:: %s\n" % (mod, directive, name) - -def format_classmember(name, directive): - parts = name.split('.') - mod, name = '.'.join(parts[:-2]), '.'.join(parts[-2:]) - return ".. currentmodule:: %s\n\n.. %s:: %s\n" % (mod, directive, name) - -def get_documented(filenames): - """ - Find out what items are documented in source/*.rst - See `get_documented_in_lines`. - - """ - documented = {} - for filename in filenames: - f = open(filename, 'r') - lines = f.read().splitlines() - documented.update(get_documented_in_lines(lines, filename=filename)) - f.close() - return documented - -def get_documented_in_docstring(name, module=None, filename=None): - """ - Find out what items are documented in the given object's docstring. - See `get_documented_in_lines`. - - """ - try: - obj, real_name = import_by_name(name) - lines = pydoc.getdoc(obj).splitlines() - return get_documented_in_lines(lines, module=name, filename=filename) - except AttributeError: - pass - except ImportError, e: - print "Failed to import '%s': %s" % (name, e) - return {} - -def get_documented_in_lines(lines, module=None, filename=None): - """ - Find out what items are documented in the given lines - - Returns - ------- - documented : dict of list of (filename, title, keyword, toctree) - Dictionary whose keys are documented names of objects. - The value is a list of locations where the object was documented. - Each location is a tuple of filename, the current section title, - the name of the directive, and the value of the :toctree: argument - (if present) of the directive. - - """ - title_underline_re = re.compile("^[-=*_^#]{3,}\s*$") - autodoc_re = re.compile(".. auto(function|method|attribute|class|exception|module)::\s*([A-Za-z0-9_.]+)\s*$") - autosummary_re = re.compile(r'^\.\.\s+autosummary::\s*') - module_re = re.compile(r'^\.\.\s+(current)?module::\s*([a-zA-Z0-9_.]+)\s*$') - autosummary_item_re = re.compile(r'^\s+([_a-zA-Z][a-zA-Z0-9_.]*)\s*.*?') - toctree_arg_re = re.compile(r'^\s+:toctree:\s*(.*?)\s*$') - - documented = {} - - current_title = [] - last_line = None - toctree = None - current_module = module - in_autosummary = False - - for line in lines: - try: - if in_autosummary: - m = toctree_arg_re.match(line) - if m: - toctree = m.group(1) - continue - - if line.strip().startswith(':'): - continue # skip options - - m = autosummary_item_re.match(line) - if m: - name = m.group(1).strip() - if current_module and not name.startswith(current_module + '.'): - name = "%s.%s" % (current_module, name) - documented.setdefault(name, []).append( - (filename, current_title, 'autosummary', toctree)) - continue - if line.strip() == '': - continue - in_autosummary = False - - m = autosummary_re.match(line) - if m: - in_autosummary = True - continue - - m = autodoc_re.search(line) - if m: - name = m.group(2).strip() - if m.group(1) == "module": - current_module = name - documented.update(get_documented_in_docstring( - name, filename=filename)) - elif current_module and not name.startswith(current_module+'.'): - name = "%s.%s" % (current_module, name) - documented.setdefault(name, []).append( - (filename, current_title, "auto" + m.group(1), None)) - continue - - m = title_underline_re.match(line) - if m and last_line: - current_title = last_line.strip() - continue - - m = module_re.match(line) - if m: - current_module = m.group(2) - continue - finally: - last_line = line - - return documented - -if __name__ == "__main__": - main() diff --git a/doc/sphinxext/numpydoc/comment_eater.py b/doc/sphinxext/numpydoc/comment_eater.py deleted file mode 100755 index e11eea90..00000000 --- a/doc/sphinxext/numpydoc/comment_eater.py +++ /dev/null @@ -1,158 +0,0 @@ -from cStringIO import StringIO -import compiler -import inspect -import textwrap -import tokenize - -from compiler_unparse import unparse - - -class Comment(object): - """ A comment block. - """ - is_comment = True - def __init__(self, start_lineno, end_lineno, text): - # int : The first line number in the block. 1-indexed. - self.start_lineno = start_lineno - # int : The last line number. Inclusive! - self.end_lineno = end_lineno - # str : The text block including '#' character but not any leading spaces. - self.text = text - - def add(self, string, start, end, line): - """ Add a new comment line. - """ - self.start_lineno = min(self.start_lineno, start[0]) - self.end_lineno = max(self.end_lineno, end[0]) - self.text += string - - def __repr__(self): - return '%s(%r, %r, %r)' % (self.__class__.__name__, self.start_lineno, - self.end_lineno, self.text) - - -class NonComment(object): - """ A non-comment block of code. - """ - is_comment = False - def __init__(self, start_lineno, end_lineno): - self.start_lineno = start_lineno - self.end_lineno = end_lineno - - def add(self, string, start, end, line): - """ Add lines to the block. - """ - if string.strip(): - # Only add if not entirely whitespace. - self.start_lineno = min(self.start_lineno, start[0]) - self.end_lineno = max(self.end_lineno, end[0]) - - def __repr__(self): - return '%s(%r, %r)' % (self.__class__.__name__, self.start_lineno, - self.end_lineno) - - -class CommentBlocker(object): - """ Pull out contiguous comment blocks. - """ - def __init__(self): - # Start with a dummy. - self.current_block = NonComment(0, 0) - - # All of the blocks seen so far. - self.blocks = [] - - # The index mapping lines of code to their associated comment blocks. - self.index = {} - - def process_file(self, file): - """ Process a file object. - """ - for token in tokenize.generate_tokens(file.next): - self.process_token(*token) - self.make_index() - - def process_token(self, kind, string, start, end, line): - """ Process a single token. - """ - if self.current_block.is_comment: - if kind == tokenize.COMMENT: - self.current_block.add(string, start, end, line) - else: - self.new_noncomment(start[0], end[0]) - else: - if kind == tokenize.COMMENT: - self.new_comment(string, start, end, line) - else: - self.current_block.add(string, start, end, line) - - def new_noncomment(self, start_lineno, end_lineno): - """ We are transitioning from a noncomment to a comment. - """ - block = NonComment(start_lineno, end_lineno) - self.blocks.append(block) - self.current_block = block - - def new_comment(self, string, start, end, line): - """ Possibly add a new comment. - - Only adds a new comment if this comment is the only thing on the line. - Otherwise, it extends the noncomment block. - """ - prefix = line[:start[1]] - if prefix.strip(): - # Oops! Trailing comment, not a comment block. - self.current_block.add(string, start, end, line) - else: - # A comment block. - block = Comment(start[0], end[0], string) - self.blocks.append(block) - self.current_block = block - - def make_index(self): - """ Make the index mapping lines of actual code to their associated - prefix comments. - """ - for prev, block in zip(self.blocks[:-1], self.blocks[1:]): - if not block.is_comment: - self.index[block.start_lineno] = prev - - def search_for_comment(self, lineno, default=None): - """ Find the comment block just before the given line number. - - Returns None (or the specified default) if there is no such block. - """ - if not self.index: - self.make_index() - block = self.index.get(lineno, None) - text = getattr(block, 'text', default) - return text - - -def strip_comment_marker(text): - """ Strip # markers at the front of a block of comment text. - """ - lines = [] - for line in text.splitlines(): - lines.append(line.lstrip('#')) - text = textwrap.dedent('\n'.join(lines)) - return text - - -def get_class_traits(klass): - """ Yield all of the documentation for trait definitions on a class object. - """ - # FIXME: gracefully handle errors here or in the caller? - source = inspect.getsource(klass) - cb = CommentBlocker() - cb.process_file(StringIO(source)) - mod_ast = compiler.parse(source) - class_ast = mod_ast.node.nodes[0] - for node in class_ast.code.nodes: - # FIXME: handle other kinds of assignments? - if isinstance(node, compiler.ast.Assign): - name = node.nodes[0].name - rhs = unparse(node.expr).strip() - doc = strip_comment_marker(cb.search_for_comment(node.lineno, default='')) - yield name, rhs, doc - diff --git a/doc/sphinxext/numpydoc/compiler_unparse.py b/doc/sphinxext/numpydoc/compiler_unparse.py deleted file mode 100755 index ffcf51b3..00000000 --- a/doc/sphinxext/numpydoc/compiler_unparse.py +++ /dev/null @@ -1,860 +0,0 @@ -""" Turn compiler.ast structures back into executable python code. - - The unparse method takes a compiler.ast tree and transforms it back into - valid python code. It is incomplete and currently only works for - import statements, function calls, function definitions, assignments, and - basic expressions. - - Inspired by python-2.5-svn/Demo/parser/unparse.py - - fixme: We may want to move to using _ast trees because the compiler for - them is about 6 times faster than compiler.compile. -""" - -import sys -import cStringIO -from compiler.ast import Const, Name, Tuple, Div, Mul, Sub, Add - -def unparse(ast, single_line_functions=False): - s = cStringIO.StringIO() - UnparseCompilerAst(ast, s, single_line_functions) - return s.getvalue().lstrip() - -op_precedence = { 'compiler.ast.Power':3, 'compiler.ast.Mul':2, 'compiler.ast.Div':2, - 'compiler.ast.Add':1, 'compiler.ast.Sub':1 } - -class UnparseCompilerAst: - """ Methods in this class recursively traverse an AST and - output source code for the abstract syntax; original formatting - is disregarged. - """ - - ######################################################################### - # object interface. - ######################################################################### - - def __init__(self, tree, file = sys.stdout, single_line_functions=False): - """ Unparser(tree, file=sys.stdout) -> None. - - Print the source for tree to file. - """ - self.f = file - self._single_func = single_line_functions - self._do_indent = True - self._indent = 0 - self._dispatch(tree) - self._write("\n") - self.f.flush() - - ######################################################################### - # Unparser private interface. - ######################################################################### - - ### format, output, and dispatch methods ################################ - - def _fill(self, text = ""): - "Indent a piece of text, according to the current indentation level" - if self._do_indent: - self._write("\n"+" "*self._indent + text) - else: - self._write(text) - - def _write(self, text): - "Append a piece of text to the current line." - self.f.write(text) - - def _enter(self): - "Print ':', and increase the indentation." - self._write(": ") - self._indent += 1 - - def _leave(self): - "Decrease the indentation level." - self._indent -= 1 - - def _dispatch(self, tree): - "_dispatcher function, _dispatching tree type T to method _T." - if isinstance(tree, list): - for t in tree: - self._dispatch(t) - return - meth = getattr(self, "_"+tree.__class__.__name__) - if tree.__class__.__name__ == 'NoneType' and not self._do_indent: - return - meth(tree) - - - ######################################################################### - # compiler.ast unparsing methods. - # - # There should be one method per concrete grammar type. They are - # organized in alphabetical order. - ######################################################################### - - def _Add(self, t): - self.__binary_op(t, '+') - - def _And(self, t): - self._write(" (") - for i, node in enumerate(t.nodes): - self._dispatch(node) - if i != len(t.nodes)-1: - self._write(") and (") - self._write(")") - - def _AssAttr(self, t): - """ Handle assigning an attribute of an object - """ - self._dispatch(t.expr) - self._write('.'+t.attrname) - - def _Assign(self, t): - """ Expression Assignment such as "a = 1". - - This only handles assignment in expressions. Keyword assignment - is handled separately. - """ - self._fill() - for target in t.nodes: - self._dispatch(target) - self._write(" = ") - self._dispatch(t.expr) - if not self._do_indent: - self._write('; ') - - def _AssName(self, t): - """ Name on left hand side of expression. - - Treat just like a name on the right side of an expression. - """ - self._Name(t) - - def _AssTuple(self, t): - """ Tuple on left hand side of an expression. - """ - - # _write each elements, separated by a comma. - for element in t.nodes[:-1]: - self._dispatch(element) - self._write(", ") - - # Handle the last one without writing comma - last_element = t.nodes[-1] - self._dispatch(last_element) - - def _AugAssign(self, t): - """ +=,-=,*=,/=,**=, etc. operations - """ - - self._fill() - self._dispatch(t.node) - self._write(' '+t.op+' ') - self._dispatch(t.expr) - if not self._do_indent: - self._write(';') - - def _Bitand(self, t): - """ Bit and operation. - """ - - for i, node in enumerate(t.nodes): - self._write("(") - self._dispatch(node) - self._write(")") - if i != len(t.nodes)-1: - self._write(" & ") - - def _Bitor(self, t): - """ Bit or operation - """ - - for i, node in enumerate(t.nodes): - self._write("(") - self._dispatch(node) - self._write(")") - if i != len(t.nodes)-1: - self._write(" | ") - - def _CallFunc(self, t): - """ Function call. - """ - self._dispatch(t.node) - self._write("(") - comma = False - for e in t.args: - if comma: self._write(", ") - else: comma = True - self._dispatch(e) - if t.star_args: - if comma: self._write(", ") - else: comma = True - self._write("*") - self._dispatch(t.star_args) - if t.dstar_args: - if comma: self._write(", ") - else: comma = True - self._write("**") - self._dispatch(t.dstar_args) - self._write(")") - - def _Compare(self, t): - self._dispatch(t.expr) - for op, expr in t.ops: - self._write(" " + op + " ") - self._dispatch(expr) - - def _Const(self, t): - """ A constant value such as an integer value, 3, or a string, "hello". - """ - self._dispatch(t.value) - - def _Decorators(self, t): - """ Handle function decorators (eg. @has_units) - """ - for node in t.nodes: - self._dispatch(node) - - def _Dict(self, t): - self._write("{") - for i, (k, v) in enumerate(t.items): - self._dispatch(k) - self._write(": ") - self._dispatch(v) - if i < len(t.items)-1: - self._write(", ") - self._write("}") - - def _Discard(self, t): - """ Node for when return value is ignored such as in "foo(a)". - """ - self._fill() - self._dispatch(t.expr) - - def _Div(self, t): - self.__binary_op(t, '/') - - def _Ellipsis(self, t): - self._write("...") - - def _From(self, t): - """ Handle "from xyz import foo, bar as baz". - """ - # fixme: Are From and ImportFrom handled differently? - self._fill("from ") - self._write(t.modname) - self._write(" import ") - for i, (name,asname) in enumerate(t.names): - if i != 0: - self._write(", ") - self._write(name) - if asname is not None: - self._write(" as "+asname) - - def _Function(self, t): - """ Handle function definitions - """ - if t.decorators is not None: - self._fill("@") - self._dispatch(t.decorators) - self._fill("def "+t.name + "(") - defaults = [None] * (len(t.argnames) - len(t.defaults)) + list(t.defaults) - for i, arg in enumerate(zip(t.argnames, defaults)): - self._write(arg[0]) - if arg[1] is not None: - self._write('=') - self._dispatch(arg[1]) - if i < len(t.argnames)-1: - self._write(', ') - self._write(")") - if self._single_func: - self._do_indent = False - self._enter() - self._dispatch(t.code) - self._leave() - self._do_indent = True - - def _Getattr(self, t): - """ Handle getting an attribute of an object - """ - if isinstance(t.expr, (Div, Mul, Sub, Add)): - self._write('(') - self._dispatch(t.expr) - self._write(')') - else: - self._dispatch(t.expr) - - self._write('.'+t.attrname) - - def _If(self, t): - self._fill() - - for i, (compare,code) in enumerate(t.tests): - if i == 0: - self._write("if ") - else: - self._write("elif ") - self._dispatch(compare) - self._enter() - self._fill() - self._dispatch(code) - self._leave() - self._write("\n") - - if t.else_ is not None: - self._write("else") - self._enter() - self._fill() - self._dispatch(t.else_) - self._leave() - self._write("\n") - - def _IfExp(self, t): - self._dispatch(t.then) - self._write(" if ") - self._dispatch(t.test) - - if t.else_ is not None: - self._write(" else (") - self._dispatch(t.else_) - self._write(")") - - def _Import(self, t): - """ Handle "import xyz.foo". - """ - self._fill("import ") - - for i, (name,asname) in enumerate(t.names): - if i != 0: - self._write(", ") - self._write(name) - if asname is not None: - self._write(" as "+asname) - - def _Keyword(self, t): - """ Keyword value assignment within function calls and definitions. - """ - self._write(t.name) - self._write("=") - self._dispatch(t.expr) - - def _List(self, t): - self._write("[") - for i,node in enumerate(t.nodes): - self._dispatch(node) - if i < len(t.nodes)-1: - self._write(", ") - self._write("]") - - def _Module(self, t): - if t.doc is not None: - self._dispatch(t.doc) - self._dispatch(t.node) - - def _Mul(self, t): - self.__binary_op(t, '*') - - def _Name(self, t): - self._write(t.name) - - def _NoneType(self, t): - self._write("None") - - def _Not(self, t): - self._write('not (') - self._dispatch(t.expr) - self._write(')') - - def _Or(self, t): - self._write(" (") - for i, node in enumerate(t.nodes): - self._dispatch(node) - if i != len(t.nodes)-1: - self._write(") or (") - self._write(")") - - def _Pass(self, t): - self._write("pass\n") - - def _Printnl(self, t): - self._fill("print ") - if t.dest: - self._write(">> ") - self._dispatch(t.dest) - self._write(", ") - comma = False - for node in t.nodes: - if comma: self._write(', ') - else: comma = True - self._dispatch(node) - - def _Power(self, t): - self.__binary_op(t, '**') - - def _Return(self, t): - self._fill("return ") - if t.value: - if isinstance(t.value, Tuple): - text = ', '.join([ name.name for name in t.value.asList() ]) - self._write(text) - else: - self._dispatch(t.value) - if not self._do_indent: - self._write('; ') - - def _Slice(self, t): - self._dispatch(t.expr) - self._write("[") - if t.lower: - self._dispatch(t.lower) - self._write(":") - if t.upper: - self._dispatch(t.upper) - #if t.step: - # self._write(":") - # self._dispatch(t.step) - self._write("]") - - def _Sliceobj(self, t): - for i, node in enumerate(t.nodes): - if i != 0: - self._write(":") - if not (isinstance(node, Const) and node.value is None): - self._dispatch(node) - - def _Stmt(self, tree): - for node in tree.nodes: - self._dispatch(node) - - def _Sub(self, t): - self.__binary_op(t, '-') - - def _Subscript(self, t): - self._dispatch(t.expr) - self._write("[") - for i, value in enumerate(t.subs): - if i != 0: - self._write(",") - self._dispatch(value) - self._write("]") - - def _TryExcept(self, t): - self._fill("try") - self._enter() - self._dispatch(t.body) - self._leave() - - for handler in t.handlers: - self._fill('except ') - self._dispatch(handler[0]) - if handler[1] is not None: - self._write(', ') - self._dispatch(handler[1]) - self._enter() - self._dispatch(handler[2]) - self._leave() - - if t.else_: - self._fill("else") - self._enter() - self._dispatch(t.else_) - self._leave() - - def _Tuple(self, t): - - if not t.nodes: - # Empty tuple. - self._write("()") - else: - self._write("(") - - # _write each elements, separated by a comma. - for element in t.nodes[:-1]: - self._dispatch(element) - self._write(", ") - - # Handle the last one without writing comma - last_element = t.nodes[-1] - self._dispatch(last_element) - - self._write(")") - - def _UnaryAdd(self, t): - self._write("+") - self._dispatch(t.expr) - - def _UnarySub(self, t): - self._write("-") - self._dispatch(t.expr) - - def _With(self, t): - self._fill('with ') - self._dispatch(t.expr) - if t.vars: - self._write(' as ') - self._dispatch(t.vars.name) - self._enter() - self._dispatch(t.body) - self._leave() - self._write('\n') - - def _int(self, t): - self._write(repr(t)) - - def __binary_op(self, t, symbol): - # Check if parenthesis are needed on left side and then dispatch - has_paren = False - left_class = str(t.left.__class__) - if (left_class in op_precedence.keys() and - op_precedence[left_class] < op_precedence[str(t.__class__)]): - has_paren = True - if has_paren: - self._write('(') - self._dispatch(t.left) - if has_paren: - self._write(')') - # Write the appropriate symbol for operator - self._write(symbol) - # Check if parenthesis are needed on the right side and then dispatch - has_paren = False - right_class = str(t.right.__class__) - if (right_class in op_precedence.keys() and - op_precedence[right_class] < op_precedence[str(t.__class__)]): - has_paren = True - if has_paren: - self._write('(') - self._dispatch(t.right) - if has_paren: - self._write(')') - - def _float(self, t): - # if t is 0.1, str(t)->'0.1' while repr(t)->'0.1000000000001' - # We prefer str here. - self._write(str(t)) - - def _str(self, t): - self._write(repr(t)) - - def _tuple(self, t): - self._write(str(t)) - - ######################################################################### - # These are the methods from the _ast modules unparse. - # - # As our needs to handle more advanced code increase, we may want to - # modify some of the methods below so that they work for compiler.ast. - ######################################################################### - -# # stmt -# def _Expr(self, tree): -# self._fill() -# self._dispatch(tree.value) -# -# def _Import(self, t): -# self._fill("import ") -# first = True -# for a in t.names: -# if first: -# first = False -# else: -# self._write(", ") -# self._write(a.name) -# if a.asname: -# self._write(" as "+a.asname) -# -## def _ImportFrom(self, t): -## self._fill("from ") -## self._write(t.module) -## self._write(" import ") -## for i, a in enumerate(t.names): -## if i == 0: -## self._write(", ") -## self._write(a.name) -## if a.asname: -## self._write(" as "+a.asname) -## # XXX(jpe) what is level for? -## -# -# def _Break(self, t): -# self._fill("break") -# -# def _Continue(self, t): -# self._fill("continue") -# -# def _Delete(self, t): -# self._fill("del ") -# self._dispatch(t.targets) -# -# def _Assert(self, t): -# self._fill("assert ") -# self._dispatch(t.test) -# if t.msg: -# self._write(", ") -# self._dispatch(t.msg) -# -# def _Exec(self, t): -# self._fill("exec ") -# self._dispatch(t.body) -# if t.globals: -# self._write(" in ") -# self._dispatch(t.globals) -# if t.locals: -# self._write(", ") -# self._dispatch(t.locals) -# -# def _Print(self, t): -# self._fill("print ") -# do_comma = False -# if t.dest: -# self._write(">>") -# self._dispatch(t.dest) -# do_comma = True -# for e in t.values: -# if do_comma:self._write(", ") -# else:do_comma=True -# self._dispatch(e) -# if not t.nl: -# self._write(",") -# -# def _Global(self, t): -# self._fill("global") -# for i, n in enumerate(t.names): -# if i != 0: -# self._write(",") -# self._write(" " + n) -# -# def _Yield(self, t): -# self._fill("yield") -# if t.value: -# self._write(" (") -# self._dispatch(t.value) -# self._write(")") -# -# def _Raise(self, t): -# self._fill('raise ') -# if t.type: -# self._dispatch(t.type) -# if t.inst: -# self._write(", ") -# self._dispatch(t.inst) -# if t.tback: -# self._write(", ") -# self._dispatch(t.tback) -# -# -# def _TryFinally(self, t): -# self._fill("try") -# self._enter() -# self._dispatch(t.body) -# self._leave() -# -# self._fill("finally") -# self._enter() -# self._dispatch(t.finalbody) -# self._leave() -# -# def _excepthandler(self, t): -# self._fill("except ") -# if t.type: -# self._dispatch(t.type) -# if t.name: -# self._write(", ") -# self._dispatch(t.name) -# self._enter() -# self._dispatch(t.body) -# self._leave() -# -# def _ClassDef(self, t): -# self._write("\n") -# self._fill("class "+t.name) -# if t.bases: -# self._write("(") -# for a in t.bases: -# self._dispatch(a) -# self._write(", ") -# self._write(")") -# self._enter() -# self._dispatch(t.body) -# self._leave() -# -# def _FunctionDef(self, t): -# self._write("\n") -# for deco in t.decorators: -# self._fill("@") -# self._dispatch(deco) -# self._fill("def "+t.name + "(") -# self._dispatch(t.args) -# self._write(")") -# self._enter() -# self._dispatch(t.body) -# self._leave() -# -# def _For(self, t): -# self._fill("for ") -# self._dispatch(t.target) -# self._write(" in ") -# self._dispatch(t.iter) -# self._enter() -# self._dispatch(t.body) -# self._leave() -# if t.orelse: -# self._fill("else") -# self._enter() -# self._dispatch(t.orelse) -# self._leave -# -# def _While(self, t): -# self._fill("while ") -# self._dispatch(t.test) -# self._enter() -# self._dispatch(t.body) -# self._leave() -# if t.orelse: -# self._fill("else") -# self._enter() -# self._dispatch(t.orelse) -# self._leave -# -# # expr -# def _Str(self, tree): -# self._write(repr(tree.s)) -## -# def _Repr(self, t): -# self._write("`") -# self._dispatch(t.value) -# self._write("`") -# -# def _Num(self, t): -# self._write(repr(t.n)) -# -# def _ListComp(self, t): -# self._write("[") -# self._dispatch(t.elt) -# for gen in t.generators: -# self._dispatch(gen) -# self._write("]") -# -# def _GeneratorExp(self, t): -# self._write("(") -# self._dispatch(t.elt) -# for gen in t.generators: -# self._dispatch(gen) -# self._write(")") -# -# def _comprehension(self, t): -# self._write(" for ") -# self._dispatch(t.target) -# self._write(" in ") -# self._dispatch(t.iter) -# for if_clause in t.ifs: -# self._write(" if ") -# self._dispatch(if_clause) -# -# def _IfExp(self, t): -# self._dispatch(t.body) -# self._write(" if ") -# self._dispatch(t.test) -# if t.orelse: -# self._write(" else ") -# self._dispatch(t.orelse) -# -# unop = {"Invert":"~", "Not": "not", "UAdd":"+", "USub":"-"} -# def _UnaryOp(self, t): -# self._write(self.unop[t.op.__class__.__name__]) -# self._write("(") -# self._dispatch(t.operand) -# self._write(")") -# -# binop = { "Add":"+", "Sub":"-", "Mult":"*", "Div":"/", "Mod":"%", -# "LShift":">>", "RShift":"<<", "BitOr":"|", "BitXor":"^", "BitAnd":"&", -# "FloorDiv":"//", "Pow": "**"} -# def _BinOp(self, t): -# self._write("(") -# self._dispatch(t.left) -# self._write(")" + self.binop[t.op.__class__.__name__] + "(") -# self._dispatch(t.right) -# self._write(")") -# -# boolops = {_ast.And: 'and', _ast.Or: 'or'} -# def _BoolOp(self, t): -# self._write("(") -# self._dispatch(t.values[0]) -# for v in t.values[1:]: -# self._write(" %s " % self.boolops[t.op.__class__]) -# self._dispatch(v) -# self._write(")") -# -# def _Attribute(self,t): -# self._dispatch(t.value) -# self._write(".") -# self._write(t.attr) -# -## def _Call(self, t): -## self._dispatch(t.func) -## self._write("(") -## comma = False -## for e in t.args: -## if comma: self._write(", ") -## else: comma = True -## self._dispatch(e) -## for e in t.keywords: -## if comma: self._write(", ") -## else: comma = True -## self._dispatch(e) -## if t.starargs: -## if comma: self._write(", ") -## else: comma = True -## self._write("*") -## self._dispatch(t.starargs) -## if t.kwargs: -## if comma: self._write(", ") -## else: comma = True -## self._write("**") -## self._dispatch(t.kwargs) -## self._write(")") -# -# # slice -# def _Index(self, t): -# self._dispatch(t.value) -# -# def _ExtSlice(self, t): -# for i, d in enumerate(t.dims): -# if i != 0: -# self._write(': ') -# self._dispatch(d) -# -# # others -# def _arguments(self, t): -# first = True -# nonDef = len(t.args)-len(t.defaults) -# for a in t.args[0:nonDef]: -# if first:first = False -# else: self._write(", ") -# self._dispatch(a) -# for a,d in zip(t.args[nonDef:], t.defaults): -# if first:first = False -# else: self._write(", ") -# self._dispatch(a), -# self._write("=") -# self._dispatch(d) -# if t.vararg: -# if first:first = False -# else: self._write(", ") -# self._write("*"+t.vararg) -# if t.kwarg: -# if first:first = False -# else: self._write(", ") -# self._write("**"+t.kwarg) -# -## def _keyword(self, t): -## self._write(t.arg) -## self._write("=") -## self._dispatch(t.value) -# -# def _Lambda(self, t): -# self._write("lambda ") -# self._dispatch(t.args) -# self._write(": ") -# self._dispatch(t.body) - - - diff --git a/doc/sphinxext/numpydoc/docscrape.py b/doc/sphinxext/numpydoc/docscrape.py deleted file mode 100755 index f374b3dd..00000000 --- a/doc/sphinxext/numpydoc/docscrape.py +++ /dev/null @@ -1,497 +0,0 @@ -"""Extract reference documentation from the NumPy source tree. - -""" - -import inspect -import textwrap -import re -import pydoc -from StringIO import StringIO -from warnings import warn -4 -class Reader(object): - """A line-based string reader. - - """ - def __init__(self, data): - """ - Parameters - ---------- - data : str - String with lines separated by '\n'. - - """ - if isinstance(data,list): - self._str = data - else: - self._str = data.split('\n') # store string as list of lines - - self.reset() - - def __getitem__(self, n): - return self._str[n] - - def reset(self): - self._l = 0 # current line nr - - def read(self): - if not self.eof(): - out = self[self._l] - self._l += 1 - return out - else: - return '' - - def seek_next_non_empty_line(self): - for l in self[self._l:]: - if l.strip(): - break - else: - self._l += 1 - - def eof(self): - return self._l >= len(self._str) - - def read_to_condition(self, condition_func): - start = self._l - for line in self[start:]: - if condition_func(line): - return self[start:self._l] - self._l += 1 - if self.eof(): - return self[start:self._l+1] - return [] - - def read_to_next_empty_line(self): - self.seek_next_non_empty_line() - def is_empty(line): - return not line.strip() - return self.read_to_condition(is_empty) - - def read_to_next_unindented_line(self): - def is_unindented(line): - return (line.strip() and (len(line.lstrip()) == len(line))) - return self.read_to_condition(is_unindented) - - def peek(self,n=0): - if self._l + n < len(self._str): - return self[self._l + n] - else: - return '' - - def is_empty(self): - return not ''.join(self._str).strip() - - -class NumpyDocString(object): - def __init__(self,docstring): - docstring = textwrap.dedent(docstring).split('\n') - - self._doc = Reader(docstring) - self._parsed_data = { - 'Signature': '', - 'Summary': [''], - 'Extended Summary': [], - 'Parameters': [], - 'Returns': [], - 'Raises': [], - 'Warns': [], - 'Other Parameters': [], - 'Attributes': [], - 'Methods': [], - 'See Also': [], - 'Notes': [], - 'Warnings': [], - 'References': '', - 'Examples': '', - 'index': {} - } - - self._parse() - - def __getitem__(self,key): - return self._parsed_data[key] - - def __setitem__(self,key,val): - if not self._parsed_data.has_key(key): - warn("Unknown section %s" % key) - else: - self._parsed_data[key] = val - - def _is_at_section(self): - self._doc.seek_next_non_empty_line() - - if self._doc.eof(): - return False - - l1 = self._doc.peek().strip() # e.g. Parameters - - if l1.startswith('.. index::'): - return True - - l2 = self._doc.peek(1).strip() # ---------- or ========== - return l2.startswith('-'*len(l1)) or l2.startswith('='*len(l1)) - - def _strip(self,doc): - i = 0 - j = 0 - for i,line in enumerate(doc): - if line.strip(): break - - for j,line in enumerate(doc[::-1]): - if line.strip(): break - - return doc[i:len(doc)-j] - - def _read_to_next_section(self): - section = self._doc.read_to_next_empty_line() - - while not self._is_at_section() and not self._doc.eof(): - if not self._doc.peek(-1).strip(): # previous line was empty - section += [''] - - section += self._doc.read_to_next_empty_line() - - return section - - def _read_sections(self): - while not self._doc.eof(): - data = self._read_to_next_section() - name = data[0].strip() - - if name.startswith('..'): # index section - yield name, data[1:] - elif len(data) < 2: - yield StopIteration - else: - yield name, self._strip(data[2:]) - - def _parse_param_list(self,content): - r = Reader(content) - params = [] - while not r.eof(): - header = r.read().strip() - if ' : ' in header: - arg_name, arg_type = header.split(' : ')[:2] - else: - arg_name, arg_type = header, '' - - desc = r.read_to_next_unindented_line() - desc = dedent_lines(desc) - - params.append((arg_name,arg_type,desc)) - - return params - - - _name_rgx = re.compile(r"^\s*(:(?P\w+):`(?P[a-zA-Z0-9_.-]+)`|" - r" (?P[a-zA-Z0-9_.-]+))\s*", re.X) - def _parse_see_also(self, content): - """ - func_name : Descriptive text - continued text - another_func_name : Descriptive text - func_name1, func_name2, :meth:`func_name`, func_name3 - - """ - items = [] - - def parse_item_name(text): - """Match ':role:`name`' or 'name'""" - m = self._name_rgx.match(text) - if m: - g = m.groups() - if g[1] is None: - return g[3], None - else: - return g[2], g[1] - raise ValueError("%s is not a item name" % text) - - def push_item(name, rest): - if not name: - return - name, role = parse_item_name(name) - items.append((name, list(rest), role)) - del rest[:] - - current_func = None - rest = [] - - for line in content: - if not line.strip(): continue - - m = self._name_rgx.match(line) - if m and line[m.end():].strip().startswith(':'): - push_item(current_func, rest) - current_func, line = line[:m.end()], line[m.end():] - rest = [line.split(':', 1)[1].strip()] - if not rest[0]: - rest = [] - elif not line.startswith(' '): - push_item(current_func, rest) - current_func = None - if ',' in line: - for func in line.split(','): - push_item(func, []) - elif line.strip(): - current_func = line - elif current_func is not None: - rest.append(line.strip()) - push_item(current_func, rest) - return items - - def _parse_index(self, section, content): - """ - .. index: default - :refguide: something, else, and more - - """ - def strip_each_in(lst): - return [s.strip() for s in lst] - - out = {} - section = section.split('::') - if len(section) > 1: - out['default'] = strip_each_in(section[1].split(','))[0] - for line in content: - line = line.split(':') - if len(line) > 2: - out[line[1]] = strip_each_in(line[2].split(',')) - return out - - def _parse_summary(self): - """Grab signature (if given) and summary""" - if self._is_at_section(): - return - - summary = self._doc.read_to_next_empty_line() - summary_str = " ".join([s.strip() for s in summary]).strip() - if re.compile('^([\w., ]+=)?\s*[\w\.]+\(.*\)$').match(summary_str): - self['Signature'] = summary_str - if not self._is_at_section(): - self['Summary'] = self._doc.read_to_next_empty_line() - else: - self['Summary'] = summary - - if not self._is_at_section(): - self['Extended Summary'] = self._read_to_next_section() - - def _parse(self): - self._doc.reset() - self._parse_summary() - - for (section,content) in self._read_sections(): - if not section.startswith('..'): - section = ' '.join([s.capitalize() for s in section.split(' ')]) - if section in ('Parameters', 'Attributes', 'Methods', - 'Returns', 'Raises', 'Warns'): - self[section] = self._parse_param_list(content) - elif section.startswith('.. index::'): - self['index'] = self._parse_index(section, content) - elif section == 'See Also': - self['See Also'] = self._parse_see_also(content) - else: - self[section] = content - - # string conversion routines - - def _str_header(self, name, symbol='-'): - return [name, len(name)*symbol] - - def _str_indent(self, doc, indent=4): - out = [] - for line in doc: - out += [' '*indent + line] - return out - - def _str_signature(self): - if self['Signature']: - return [self['Signature'].replace('*','\*')] + [''] - else: - return [''] - - def _str_summary(self): - if self['Summary']: - return self['Summary'] + [''] - else: - return [] - - def _str_extended_summary(self): - if self['Extended Summary']: - return self['Extended Summary'] + [''] - else: - return [] - - def _str_param_list(self, name): - out = [] - if self[name]: - out += self._str_header(name) - for param,param_type,desc in self[name]: - out += ['%s : %s' % (param, param_type)] - out += self._str_indent(desc) - out += [''] - return out - - def _str_section(self, name): - out = [] - if self[name]: - out += self._str_header(name) - out += self[name] - out += [''] - return out - - def _str_see_also(self, func_role): - if not self['See Also']: return [] - out = [] - out += self._str_header("See Also") - last_had_desc = True - for func, desc, role in self['See Also']: - if role: - link = ':%s:`%s`' % (role, func) - elif func_role: - link = ':%s:`%s`' % (func_role, func) - else: - link = "`%s`_" % func - if desc or last_had_desc: - out += [''] - out += [link] - else: - out[-1] += ", %s" % link - if desc: - out += self._str_indent([' '.join(desc)]) - last_had_desc = True - else: - last_had_desc = False - out += [''] - return out - - def _str_index(self): - idx = self['index'] - out = [] - out += ['.. index:: %s' % idx.get('default','')] - for section, references in idx.iteritems(): - if section == 'default': - continue - out += [' :%s: %s' % (section, ', '.join(references))] - return out - - def __str__(self, func_role=''): - out = [] - out += self._str_signature() - out += self._str_summary() - out += self._str_extended_summary() - for param_list in ('Parameters','Returns','Raises'): - out += self._str_param_list(param_list) - out += self._str_section('Warnings') - out += self._str_see_also(func_role) - for s in ('Notes','References','Examples'): - out += self._str_section(s) - out += self._str_index() - return '\n'.join(out) - - -def indent(str,indent=4): - indent_str = ' '*indent - if str is None: - return indent_str - lines = str.split('\n') - return '\n'.join(indent_str + l for l in lines) - -def dedent_lines(lines): - """Deindent a list of lines maximally""" - return textwrap.dedent("\n".join(lines)).split("\n") - -def header(text, style='-'): - return text + '\n' + style*len(text) + '\n' - - -class FunctionDoc(NumpyDocString): - def __init__(self, func, role='func', doc=None): - self._f = func - self._role = role # e.g. "func" or "meth" - if doc is None: - doc = inspect.getdoc(func) or '' - try: - NumpyDocString.__init__(self, doc) - except ValueError, e: - print '*'*78 - print "ERROR: '%s' while parsing `%s`" % (e, self._f) - print '*'*78 - #print "Docstring follows:" - #print doclines - #print '='*78 - - if not self['Signature']: - func, func_name = self.get_func() - try: - # try to read signature - argspec = inspect.getargspec(func) - argspec = inspect.formatargspec(*argspec) - argspec = argspec.replace('*','\*') - signature = '%s%s' % (func_name, argspec) - except TypeError, e: - signature = '%s()' % func_name - self['Signature'] = signature - - def get_func(self): - func_name = getattr(self._f, '__name__', self.__class__.__name__) - if inspect.isclass(self._f): - func = getattr(self._f, '__call__', self._f.__init__) - else: - func = self._f - return func, func_name - - def __str__(self): - out = '' - - func, func_name = self.get_func() - signature = self['Signature'].replace('*', '\*') - - roles = {'func': 'function', - 'meth': 'method'} - - if self._role: - if not roles.has_key(self._role): - print "Warning: invalid role %s" % self._role - out += '.. %s:: %s\n \n\n' % (roles.get(self._role,''), - func_name) - - out += super(FunctionDoc, self).__str__(func_role=self._role) - return out - - -class ClassDoc(NumpyDocString): - def __init__(self,cls,modulename='',func_doc=FunctionDoc,doc=None): - if not inspect.isclass(cls): - raise ValueError("Initialise using a class. Got %r" % cls) - self._cls = cls - - if modulename and not modulename.endswith('.'): - modulename += '.' - self._mod = modulename - self._name = cls.__name__ - self._func_doc = func_doc - - if doc is None: - doc = pydoc.getdoc(cls) - - NumpyDocString.__init__(self, doc) - - @property - def methods(self): - return [name for name,func in inspect.getmembers(self._cls) - if not name.startswith('_') and callable(func)] - - def __str__(self): - out = '' - out += super(ClassDoc, self).__str__() - out += "\n\n" - - #for m in self.methods: - # print "Parsing `%s`" % m - # out += str(self._func_doc(getattr(self._cls,m), 'meth')) + '\n\n' - # out += '.. index::\n single: %s; %s\n\n' % (self._name, m) - - return out - - diff --git a/doc/sphinxext/numpydoc/docscrape_sphinx.py b/doc/sphinxext/numpydoc/docscrape_sphinx.py deleted file mode 100755 index 7293fc79..00000000 --- a/doc/sphinxext/numpydoc/docscrape_sphinx.py +++ /dev/null @@ -1,149 +0,0 @@ -import re, inspect, textwrap, pydoc -import sphinx -from docscrape import NumpyDocString, FunctionDoc, ClassDoc - -class SphinxDocString(NumpyDocString): - # string conversion routines - def _str_header(self, name, symbol='`'): - return ['.. rubric:: ' + name, ''] - - def _str_field_list(self, name): - return [':' + name + ':'] - - def _str_indent(self, doc, indent=4): - out = [] - for line in doc: - out += [' '*indent + line] - return out - - def _str_signature(self): - return [''] - if self['Signature']: - return ['``%s``' % self['Signature']] + [''] - else: - return [''] - - def _str_summary(self): - return self['Summary'] + [''] - - def _str_extended_summary(self): - return self['Extended Summary'] + [''] - - def _str_param_list(self, name): - out = [] - if self[name]: - out += self._str_field_list(name) - out += [''] - for param,param_type,desc in self[name]: - out += self._str_indent(['**%s** : %s' % (param.strip(), - param_type)]) - out += [''] - out += self._str_indent(desc,8) - out += [''] - return out - - def _str_section(self, name): - out = [] - if self[name]: - out += self._str_header(name) - out += [''] - content = textwrap.dedent("\n".join(self[name])).split("\n") - out += content - out += [''] - return out - - def _str_see_also(self, func_role): - out = [] - if self['See Also']: - see_also = super(SphinxDocString, self)._str_see_also(func_role) - out = ['.. seealso::', ''] - out += self._str_indent(see_also[2:]) - return out - - def _str_warnings(self): - out = [] - if self['Warnings']: - out = ['.. warning::', ''] - out += self._str_indent(self['Warnings']) - return out - - def _str_index(self): - idx = self['index'] - out = [] - if len(idx) == 0: - return out - - out += ['.. index:: %s' % idx.get('default','')] - for section, references in idx.iteritems(): - if section == 'default': - continue - elif section == 'refguide': - out += [' single: %s' % (', '.join(references))] - else: - out += [' %s: %s' % (section, ','.join(references))] - return out - - def _str_references(self): - out = [] - if self['References']: - out += self._str_header('References') - if isinstance(self['References'], str): - self['References'] = [self['References']] - out.extend(self['References']) - out += [''] - # Latex collects all references to a separate bibliography, - # so we need to insert links to it - if sphinx.__version__ >= 0.6: - out += ['.. only:: latex',''] - else: - out += ['.. latexonly::',''] - items = [] - for line in self['References']: - m = re.match(r'.. \[([a-z0-9._-]+)\]', line, re.I) - if m: - items.append(m.group(1)) - out += [' ' + ", ".join(["[%s]_" % item for item in items]), ''] - return out - - def __str__(self, indent=0, func_role="obj"): - out = [] - out += self._str_signature() - out += self._str_index() + [''] - out += self._str_summary() - out += self._str_extended_summary() - for param_list in ('Parameters', 'Attributes', 'Methods', - 'Returns','Raises'): - out += self._str_param_list(param_list) - out += self._str_warnings() - out += self._str_see_also(func_role) - out += self._str_section('Notes') - out += self._str_references() - out += self._str_section('Examples') - out = self._str_indent(out,indent) - return '\n'.join(out) - -class SphinxFunctionDoc(SphinxDocString, FunctionDoc): - pass - -class SphinxClassDoc(SphinxDocString, ClassDoc): - pass - -def get_doc_object(obj, what=None, doc=None): - if what is None: - if inspect.isclass(obj): - what = 'class' - elif inspect.ismodule(obj): - what = 'module' - elif callable(obj): - what = 'function' - else: - what = 'object' - if what == 'class': - return SphinxClassDoc(obj, '', func_doc=SphinxFunctionDoc, doc=doc) - elif what in ('function', 'method'): - return SphinxFunctionDoc(obj, '', doc=doc) - else: - if doc is None: - doc = pydoc.getdoc(obj) - return SphinxDocString(doc) - diff --git a/doc/sphinxext/numpydoc/numpydoc.py b/doc/sphinxext/numpydoc/numpydoc.py deleted file mode 100755 index edd58597..00000000 --- a/doc/sphinxext/numpydoc/numpydoc.py +++ /dev/null @@ -1,117 +0,0 @@ -""" -======== -numpydoc -======== - -Sphinx extension that handles docstrings in the Numpy standard format. [1] - -It will: - -- Convert Parameters etc. sections to field lists. -- Convert See Also section to a See also entry. -- Renumber references. -- Extract the signature from the docstring, if it can't be determined otherwise. - -.. [1] http://projects.scipy.org/numpy/wiki/CodingStyleGuidelines#docstring-standard - -""" - -import os, re, pydoc -from docscrape_sphinx import get_doc_object, SphinxDocString -import inspect - -def mangle_docstrings(app, what, name, obj, options, lines, - reference_offset=[0]): - - if what == 'module': - # Strip top title - title_re = re.compile(r'^\s*[#*=]{4,}\n[a-z0-9 -]+\n[#*=]{4,}\s*', - re.I|re.S) - lines[:] = title_re.sub('', "\n".join(lines)).split("\n") - else: - doc = get_doc_object(obj, what, "\n".join(lines)) - lines[:] = str(doc).split("\n") - - if app.config.numpydoc_edit_link and hasattr(obj, '__name__') and \ - obj.__name__: - if hasattr(obj, '__module__'): - v = dict(full_name="%s.%s" % (obj.__module__, obj.__name__)) - else: - v = dict(full_name=obj.__name__) - lines += ['', '.. htmlonly::', ''] - lines += [' %s' % x for x in - (app.config.numpydoc_edit_link % v).split("\n")] - - # replace reference numbers so that there are no duplicates - references = [] - for line in lines: - line = line.strip() - m = re.match(r'^.. \[([a-z0-9_.-])\]', line, re.I) - if m: - references.append(m.group(1)) - - # start renaming from the longest string, to avoid overwriting parts - references.sort(key=lambda x: -len(x)) - if references: - for i, line in enumerate(lines): - for r in references: - if re.match(r'^\d+$', r): - new_r = "R%d" % (reference_offset[0] + int(r)) - else: - new_r = "%s%d" % (r, reference_offset[0]) - lines[i] = lines[i].replace('[%s]_' % r, - '[%s]_' % new_r) - lines[i] = lines[i].replace('.. [%s]' % r, - '.. [%s]' % new_r) - - reference_offset[0] += len(references) - -def mangle_signature(app, what, name, obj, options, sig, retann): - # Do not try to inspect classes that don't define `__init__` - if (inspect.isclass(obj) and - 'initializes x; see ' in pydoc.getdoc(obj.__init__)): - return '', '' - - if not (callable(obj) or hasattr(obj, '__argspec_is_invalid_')): return - if not hasattr(obj, '__doc__'): return - - doc = SphinxDocString(pydoc.getdoc(obj)) - if doc['Signature']: - sig = re.sub("^[^(]*", "", doc['Signature']) - return sig, '' - -def initialize(app): - try: - app.connect('autodoc-process-signature', mangle_signature) - except: - monkeypatch_sphinx_ext_autodoc() - -def setup(app, get_doc_object_=get_doc_object): - global get_doc_object - get_doc_object = get_doc_object_ - - app.connect('autodoc-process-docstring', mangle_docstrings) - app.connect('builder-inited', initialize) - app.add_config_value('numpydoc_edit_link', None, True) - -#------------------------------------------------------------------------------ -# Monkeypatch sphinx.ext.autodoc to accept argspecless autodocs (Sphinx < 0.5) -#------------------------------------------------------------------------------ - -def monkeypatch_sphinx_ext_autodoc(): - global _original_format_signature - import sphinx.ext.autodoc - - if sphinx.ext.autodoc.format_signature is our_format_signature: - return - - print "[numpydoc] Monkeypatching sphinx.ext.autodoc ..." - _original_format_signature = sphinx.ext.autodoc.format_signature - sphinx.ext.autodoc.format_signature = our_format_signature - -def our_format_signature(what, obj): - r = mangle_signature(None, what, None, obj, None, None, None) - if r is not None: - return r[0] - else: - return _original_format_signature(what, obj) diff --git a/doc/sphinxext/numpydoc/only_directives.py b/doc/sphinxext/numpydoc/only_directives.py deleted file mode 100755 index c0dff7e6..00000000 --- a/doc/sphinxext/numpydoc/only_directives.py +++ /dev/null @@ -1,96 +0,0 @@ -# -# A pair of directives for inserting content that will only appear in -# either html or latex. -# - -from docutils.nodes import Body, Element -from docutils.writers.html4css1 import HTMLTranslator -try: - from sphinx.latexwriter import LaTeXTranslator -except ImportError: - from sphinx.writers.latex import LaTeXTranslator - - import warnings - warnings.warn("The numpydoc.only_directives module is deprecated;" - "please use the only:: directive available in Sphinx >= 0.6", - DeprecationWarning, stacklevel=2) - -from docutils.parsers.rst import directives - -class html_only(Body, Element): - pass - -class latex_only(Body, Element): - pass - -def run(content, node_class, state, content_offset): - text = '\n'.join(content) - node = node_class(text) - state.nested_parse(content, content_offset, node) - return [node] - -try: - from docutils.parsers.rst import Directive -except ImportError: - from docutils.parsers.rst.directives import _directives - - def html_only_directive(name, arguments, options, content, lineno, - content_offset, block_text, state, state_machine): - return run(content, html_only, state, content_offset) - - def latex_only_directive(name, arguments, options, content, lineno, - content_offset, block_text, state, state_machine): - return run(content, latex_only, state, content_offset) - - for func in (html_only_directive, latex_only_directive): - func.content = 1 - func.options = {} - func.arguments = None - - _directives['htmlonly'] = html_only_directive - _directives['latexonly'] = latex_only_directive -else: - class OnlyDirective(Directive): - has_content = True - required_arguments = 0 - optional_arguments = 0 - final_argument_whitespace = True - option_spec = {} - - def run(self): - self.assert_has_content() - return run(self.content, self.node_class, - self.state, self.content_offset) - - class HtmlOnlyDirective(OnlyDirective): - node_class = html_only - - class LatexOnlyDirective(OnlyDirective): - node_class = latex_only - - directives.register_directive('htmlonly', HtmlOnlyDirective) - directives.register_directive('latexonly', LatexOnlyDirective) - -def setup(app): - app.add_node(html_only) - app.add_node(latex_only) - - # Add visit/depart methods to HTML-Translator: - def visit_perform(self, node): - pass - def depart_perform(self, node): - pass - def visit_ignore(self, node): - node.children = [] - def depart_ignore(self, node): - node.children = [] - - HTMLTranslator.visit_html_only = visit_perform - HTMLTranslator.depart_html_only = depart_perform - HTMLTranslator.visit_latex_only = visit_ignore - HTMLTranslator.depart_latex_only = depart_ignore - - LaTeXTranslator.visit_html_only = visit_ignore - LaTeXTranslator.depart_html_only = depart_ignore - LaTeXTranslator.visit_latex_only = visit_perform - LaTeXTranslator.depart_latex_only = depart_perform diff --git a/doc/sphinxext/numpydoc/phantom_import.py b/doc/sphinxext/numpydoc/phantom_import.py deleted file mode 100755 index c77eeb54..00000000 --- a/doc/sphinxext/numpydoc/phantom_import.py +++ /dev/null @@ -1,162 +0,0 @@ -""" -============== -phantom_import -============== - -Sphinx extension to make directives from ``sphinx.ext.autodoc`` and similar -extensions to use docstrings loaded from an XML file. - -This extension loads an XML file in the Pydocweb format [1] and -creates a dummy module that contains the specified docstrings. This -can be used to get the current docstrings from a Pydocweb instance -without needing to rebuild the documented module. - -.. [1] http://code.google.com/p/pydocweb - -""" -import imp, sys, compiler, types, os, inspect, re - -def setup(app): - app.connect('builder-inited', initialize) - app.add_config_value('phantom_import_file', None, True) - -def initialize(app): - fn = app.config.phantom_import_file - if (fn and os.path.isfile(fn)): - print "[numpydoc] Phantom importing modules from", fn, "..." - import_phantom_module(fn) - -#------------------------------------------------------------------------------ -# Creating 'phantom' modules from an XML description -#------------------------------------------------------------------------------ -def import_phantom_module(xml_file): - """ - Insert a fake Python module to sys.modules, based on a XML file. - - The XML file is expected to conform to Pydocweb DTD. The fake - module will contain dummy objects, which guarantee the following: - - - Docstrings are correct. - - Class inheritance relationships are correct (if present in XML). - - Function argspec is *NOT* correct (even if present in XML). - Instead, the function signature is prepended to the function docstring. - - Class attributes are *NOT* correct; instead, they are dummy objects. - - Parameters - ---------- - xml_file : str - Name of an XML file to read - - """ - import lxml.etree as etree - - object_cache = {} - - tree = etree.parse(xml_file) - root = tree.getroot() - - # Sort items so that - # - Base classes come before classes inherited from them - # - Modules come before their contents - all_nodes = dict([(n.attrib['id'], n) for n in root]) - - def _get_bases(node, recurse=False): - bases = [x.attrib['ref'] for x in node.findall('base')] - if recurse: - j = 0 - while True: - try: - b = bases[j] - except IndexError: break - if b in all_nodes: - bases.extend(_get_bases(all_nodes[b])) - j += 1 - return bases - - type_index = ['module', 'class', 'callable', 'object'] - - def base_cmp(a, b): - x = cmp(type_index.index(a.tag), type_index.index(b.tag)) - if x != 0: return x - - if a.tag == 'class' and b.tag == 'class': - a_bases = _get_bases(a, recurse=True) - b_bases = _get_bases(b, recurse=True) - x = cmp(len(a_bases), len(b_bases)) - if x != 0: return x - if a.attrib['id'] in b_bases: return -1 - if b.attrib['id'] in a_bases: return 1 - - return cmp(a.attrib['id'].count('.'), b.attrib['id'].count('.')) - - nodes = root.getchildren() - nodes.sort(base_cmp) - - # Create phantom items - for node in nodes: - name = node.attrib['id'] - doc = (node.text or '').decode('string-escape') + "\n" - if doc == "\n": doc = "" - - # create parent, if missing - parent = name - while True: - parent = '.'.join(parent.split('.')[:-1]) - if not parent: break - if parent in object_cache: break - obj = imp.new_module(parent) - object_cache[parent] = obj - sys.modules[parent] = obj - - # create object - if node.tag == 'module': - obj = imp.new_module(name) - obj.__doc__ = doc - sys.modules[name] = obj - elif node.tag == 'class': - bases = [object_cache[b] for b in _get_bases(node) - if b in object_cache] - bases.append(object) - init = lambda self: None - init.__doc__ = doc - obj = type(name, tuple(bases), {'__doc__': doc, '__init__': init}) - obj.__name__ = name.split('.')[-1] - elif node.tag == 'callable': - funcname = node.attrib['id'].split('.')[-1] - argspec = node.attrib.get('argspec') - if argspec: - argspec = re.sub('^[^(]*', '', argspec) - doc = "%s%s\n\n%s" % (funcname, argspec, doc) - obj = lambda: 0 - obj.__argspec_is_invalid_ = True - obj.func_name = funcname - obj.__name__ = name - obj.__doc__ = doc - if inspect.isclass(object_cache[parent]): - obj.__objclass__ = object_cache[parent] - else: - class Dummy(object): pass - obj = Dummy() - obj.__name__ = name - obj.__doc__ = doc - if inspect.isclass(object_cache[parent]): - obj.__get__ = lambda: None - object_cache[name] = obj - - if parent: - if inspect.ismodule(object_cache[parent]): - obj.__module__ = parent - setattr(object_cache[parent], name.split('.')[-1], obj) - - # Populate items - for node in root: - obj = object_cache.get(node.attrib['id']) - if obj is None: continue - for ref in node.findall('ref'): - if node.tag == 'class': - if ref.attrib['ref'].startswith(node.attrib['id'] + '.'): - setattr(obj, ref.attrib['name'], - object_cache.get(ref.attrib['ref'])) - else: - setattr(obj, ref.attrib['name'], - object_cache.get(ref.attrib['ref'])) diff --git a/doc/sphinxext/numpydoc/plot_directive.py b/doc/sphinxext/numpydoc/plot_directive.py deleted file mode 100755 index 45b4c3f7..00000000 --- a/doc/sphinxext/numpydoc/plot_directive.py +++ /dev/null @@ -1,477 +0,0 @@ -""" -A special directive for generating a matplotlib plot. - -.. warning:: - - This is a hacked version of plot_directive.py from Matplotlib. - It's very much subject to change! - -Usage ------ - -Can be used like this:: - - .. plot:: examples/example.py - - .. plot:: - - import matplotlib.pyplot as plt - plt.plot([1,2,3], [4,5,6]) - - .. plot:: - - A plotting example: - - >>> import matplotlib.pyplot as plt - >>> plt.plot([1,2,3], [4,5,6]) - -The content is interpreted as doctest formatted if it has a line starting -with ``>>>``. - -The ``plot`` directive supports the options - - format : {'python', 'doctest'} - Specify the format of the input - include-source : bool - Whether to display the source code. Default can be changed in conf.py - -and the ``image`` directive options ``alt``, ``height``, ``width``, -``scale``, ``align``, ``class``. - -Configuration options ---------------------- - -The plot directive has the following configuration options: - - plot_output_dir - Directory (relative to config file) where to store plot output. - Should be inside the static directory. (Default: 'static') - - plot_pre_code - Code that should be executed before each plot. - - plot_rcparams - Dictionary of Matplotlib rc-parameter overrides. - Has 'sane' defaults. - - plot_include_source - Default value for the include-source option - - plot_formats - The set of files to generate. Default: ['png', 'pdf', 'hires.png'], - ie. everything. - -TODO ----- - -* Don't put temp files to _static directory, but do function in the way - the pngmath directive works, and plot figures only during output writing. - -* Refactor Latex output; now it's plain images, but it would be nice - to make them appear side-by-side, or in floats. - -""" - -import sys, os, glob, shutil, imp, warnings, cStringIO, re, textwrap - -import warnings -warnings.warn("A plot_directive module is also available under " - "matplotlib.sphinxext; expect this numpydoc.plot_directive " - "module to be deprecated after relevant features have been " - "integrated there.", - FutureWarning, stacklevel=2) - -def setup(app): - setup.app = app - setup.config = app.config - setup.confdir = app.confdir - - static_path = '_static' - if hasattr(app.config, 'html_static_path') and app.config.html_static_path: - static_path = app.config.html_static_path[0] - - app.add_config_value('plot_output_dir', static_path, True) - app.add_config_value('plot_pre_code', '', True) - app.add_config_value('plot_rcparams', sane_rcparameters, True) - app.add_config_value('plot_include_source', False, True) - app.add_config_value('plot_formats', ['png', 'hires.png', 'pdf'], True) - - app.add_directive('plot', plot_directive, True, (0, 1, False), - **plot_directive_options) - -sane_rcparameters = { - 'font.size': 9, - 'axes.titlesize': 9, - 'axes.labelsize': 9, - 'xtick.labelsize': 9, - 'ytick.labelsize': 9, - 'legend.fontsize': 9, - 'figure.figsize': (4, 3), -} - -#------------------------------------------------------------------------------ -# Run code and capture figures -#------------------------------------------------------------------------------ - -import matplotlib -import matplotlib.cbook as cbook -matplotlib.use('Agg') -import matplotlib.pyplot as plt -import matplotlib.image as image -from matplotlib import _pylab_helpers - -def contains_doctest(text): - r = re.compile(r'^\s*>>>', re.M) - m = r.match(text) - return bool(m) - -def unescape_doctest(text): - """ - Extract code from a piece of text, which contains either Python code - or doctests. - - """ - if not contains_doctest(text): - return text - - code = "" - for line in text.split("\n"): - m = re.match(r'^\s*(>>>|...) (.*)$', line) - if m: - code += m.group(2) + "\n" - elif line.strip(): - code += "# " + line.strip() + "\n" - else: - code += "\n" - return code - -def run_code(code, code_path): - # Change the working directory to the directory of the example, so - # it can get at its data files, if any. - pwd = os.getcwd() - old_sys_path = list(sys.path) - if code_path is not None: - dirname = os.path.abspath(os.path.dirname(code_path)) - os.chdir(dirname) - sys.path.insert(0, dirname) - - # Redirect stdout - stdout = sys.stdout - sys.stdout = cStringIO.StringIO() - - try: - code = unescape_doctest(code) - ns = {} - exec setup.config.plot_pre_code in ns - exec code in ns - finally: - os.chdir(pwd) - sys.path[:] = old_sys_path - sys.stdout = stdout - return ns - - -#------------------------------------------------------------------------------ -# Generating figures -#------------------------------------------------------------------------------ - -def out_of_date(original, derived): - """ - Returns True if derivative is out-of-date wrt original, - both of which are full file paths. - """ - return (not os.path.exists(derived) - or os.stat(derived).st_mtime < os.stat(original).st_mtime) - - -def makefig(code, code_path, output_dir, output_base, config): - """ - run a pyplot script and save the low and high res PNGs and a PDF in _static - - """ - - included_formats = config.plot_formats - if type(included_formats) is str: - included_formats = eval(included_formats) - - formats = [x for x in [('png', 80), ('hires.png', 200), ('pdf', 50)] - if x[0] in config.plot_formats] - - all_exists = True - - # Look for single-figure output files first - for format, dpi in formats: - output_path = os.path.join(output_dir, '%s.%s' % (output_base, format)) - if out_of_date(code_path, output_path): - all_exists = False - break - - if all_exists: - return [output_base] - - # Then look for multi-figure output files - image_names = [] - for i in xrange(1000): - image_names.append('%s_%02d' % (output_base, i)) - for format, dpi in formats: - output_path = os.path.join(output_dir, - '%s.%s' % (image_names[-1], format)) - if out_of_date(code_path, output_path): - all_exists = False - break - if not all_exists: - # assume that if we have one, we have them all - all_exists = (i > 0) - break - - if all_exists: - return image_names - - # We didn't find the files, so build them - print "-- Plotting figures %s" % output_base - - # Clear between runs - plt.close('all') - - # Reset figure parameters - matplotlib.rcdefaults() - matplotlib.rcParams.update(config.plot_rcparams) - - # Run code - run_code(code, code_path) - - # Collect images - image_names = [] - - fig_managers = _pylab_helpers.Gcf.get_all_fig_managers() - for i, figman in enumerate(fig_managers): - if len(fig_managers) == 1: - name = output_base - else: - name = "%s_%02d" % (output_base, i) - image_names.append(name) - for format, dpi in formats: - path = os.path.join(output_dir, '%s.%s' % (name, format)) - figman.canvas.figure.savefig(path, dpi=dpi) - - return image_names - -#------------------------------------------------------------------------------ -# Generating output -#------------------------------------------------------------------------------ - -from docutils import nodes, utils -import jinja - -TEMPLATE = """ -{{source_code}} - -.. htmlonly:: - - {% if source_code %} - (`Source code <{{source_link}}>`__) - {% endif %} - - .. admonition:: Output - :class: plot-output - - {% for name in image_names %} - .. figure:: {{link_dir}}/{{name}}.png - {%- for option in options %} - {{option}} - {% endfor %} - - ( - {%- if not source_code %}`Source code <{{source_link}}>`__, {% endif -%} - `PNG <{{link_dir}}/{{name}}.hires.png>`__, - `PDF <{{link_dir}}/{{name}}.pdf>`__) - {% endfor %} - -.. latexonly:: - - {% for name in image_names %} - .. image:: {{link_dir}}/{{name}}.pdf - {% endfor %} - -""" - -def run(arguments, content, options, state_machine, state, lineno): - if arguments and content: - raise RuntimeError("plot:: directive can't have both args and content") - - document = state_machine.document - config = document.settings.env.config - - options.setdefault('include-source', config.plot_include_source) - if options['include-source'] is None: - options['include-source'] = config.plot_include_source - - # determine input - rst_file = document.attributes['source'] - rst_dir = os.path.dirname(rst_file) - - if arguments: - file_name = os.path.join(rst_dir, directives.uri(arguments[0])) - code = open(file_name, 'r').read() - output_base = os.path.basename(file_name) - else: - file_name = rst_file - code = textwrap.dedent("\n".join(map(str, content))) - counter = document.attributes.get('_plot_counter', 0) + 1 - document.attributes['_plot_counter'] = counter - output_base = '%d-%s' % (counter, os.path.basename(file_name)) - - rel_name = relpath(file_name, setup.confdir) - - base, ext = os.path.splitext(output_base) - if ext in ('.py', '.rst', '.txt'): - output_base = base - - # is it in doctest format? - is_doctest = contains_doctest(code) - if options.has_key('format'): - if options['format'] == 'python': - is_doctest = False - else: - is_doctest = True - - # determine output - file_rel_dir = os.path.dirname(rel_name) - while file_rel_dir.startswith(os.path.sep): - file_rel_dir = file_rel_dir[1:] - - output_dir = os.path.join(setup.confdir, setup.config.plot_output_dir, - file_rel_dir) - - if not os.path.exists(output_dir): - cbook.mkdirs(output_dir) - - # copy script - target_name = os.path.join(output_dir, output_base) - f = open(target_name, 'w') - f.write(unescape_doctest(code)) - f.close() - - source_link = relpath(target_name, rst_dir) - - # determine relative reference - link_dir = relpath(output_dir, rst_dir) - - # make figures - try: - image_names = makefig(code, file_name, output_dir, output_base, config) - except RuntimeError, err: - reporter = state.memo.reporter - sm = reporter.system_message(3, "Exception occurred rendering plot", - line=lineno) - return [sm] - - # generate output - if options['include-source']: - if is_doctest: - lines = [''] - else: - lines = ['.. code-block:: python', ''] - lines += [' %s' % row.rstrip() for row in code.split('\n')] - source_code = "\n".join(lines) - else: - source_code = "" - - opts = [':%s: %s' % (key, val) for key, val in options.items() - if key in ('alt', 'height', 'width', 'scale', 'align', 'class')] - - result = jinja.from_string(TEMPLATE).render( - link_dir=link_dir.replace(os.path.sep, '/'), - source_link=source_link, - options=opts, - image_names=image_names, - source_code=source_code) - - lines = result.split("\n") - if len(lines): - state_machine.insert_input( - lines, state_machine.input_lines.source(0)) - - return [] - - -if hasattr(os.path, 'relpath'): - relpath = os.path.relpath -else: - def relpath(target, base=os.curdir): - """ - Return a relative path to the target from either the current - dir or an optional base dir. Base can be a directory - specified either as absolute or relative to current dir. - """ - - if not os.path.exists(target): - raise OSError, 'Target does not exist: '+target - - if not os.path.isdir(base): - raise OSError, 'Base is not a directory or does not exist: '+base - - base_list = (os.path.abspath(base)).split(os.sep) - target_list = (os.path.abspath(target)).split(os.sep) - - # On the windows platform the target may be on a completely - # different drive from the base. - if os.name in ['nt','dos','os2'] and base_list[0] <> target_list[0]: - raise OSError, 'Target is on a different drive to base. Target: '+target_list[0].upper()+', base: '+base_list[0].upper() - - # Starting from the filepath root, work out how much of the - # filepath is shared by base and target. - for i in range(min(len(base_list), len(target_list))): - if base_list[i] <> target_list[i]: break - else: - # If we broke out of the loop, i is pointing to the first - # differing path elements. If we didn't break out of the - # loop, i is pointing to identical path elements. - # Increment i so that in all cases it points to the first - # differing path elements. - i+=1 - - rel_list = [os.pardir] * (len(base_list)-i) + target_list[i:] - return os.path.join(*rel_list) - -#------------------------------------------------------------------------------ -# plot:: directive registration etc. -#------------------------------------------------------------------------------ - -from docutils.parsers.rst import directives -try: - # docutils 0.4 - from docutils.parsers.rst.directives.images import align -except ImportError: - # docutils 0.5 - from docutils.parsers.rst.directives.images import Image - align = Image.align - -def plot_directive(name, arguments, options, content, lineno, - content_offset, block_text, state, state_machine): - return run(arguments, content, options, state_machine, state, lineno) - -plot_directive.__doc__ = __doc__ - -def _option_boolean(arg): - if not arg or not arg.strip(): - return None - elif arg.strip().lower() in ('no', '0', 'false'): - return False - elif arg.strip().lower() in ('yes', '1', 'true'): - return True - else: - raise ValueError('"%s" unknown boolean' % arg) - -def _option_format(arg): - return directives.choice(arg, ('python', 'lisp')) - -plot_directive_options = {'alt': directives.unchanged, - 'height': directives.length_or_unitless, - 'width': directives.length_or_percentage_or_unitless, - 'scale': directives.nonnegative_int, - 'align': align, - 'class': directives.class_option, - 'include-source': _option_boolean, - 'format': _option_format, - } diff --git a/doc/sphinxext/numpydoc/setup.py b/doc/sphinxext/numpydoc/setup.py deleted file mode 100755 index db4609a0..00000000 --- a/doc/sphinxext/numpydoc/setup.py +++ /dev/null @@ -1,31 +0,0 @@ -from distutils.core import setup -import setuptools -import sys, os - -version = "0.2.dev" - -setup( - name="numpydoc", - packages=["numpydoc"], - package_dir={"numpydoc": ""}, - version=version, - description="Sphinx extension to support docstrings in Numpy format", - # classifiers from http://pypi.python.org/pypi?%3Aaction=list_classifiers - classifiers=["Development Status :: 3 - Alpha", - "Environment :: Plugins", - "License :: OSI Approved :: BSD License", - "Topic :: Documentation"], - keywords="sphinx numpy", - author="Pauli Virtanen and others", - author_email="pav@iki.fi", - url="http://projects.scipy.org/numpy/browser/trunk/doc/sphinxext", - license="BSD", - zip_safe=False, - install_requires=["Sphinx >= 0.5"], - package_data={'numpydoc': 'tests'}, - entry_points={ - "console_scripts": [ - "autosummary_generate = numpydoc.autosummary_generate:main", - ], - }, -) diff --git a/doc/sphinxext/numpydoc/tests/test_docscrape.py b/doc/sphinxext/numpydoc/tests/test_docscrape.py deleted file mode 100755 index 15c9b17f..00000000 --- a/doc/sphinxext/numpydoc/tests/test_docscrape.py +++ /dev/null @@ -1,490 +0,0 @@ -# -*- encoding:utf-8 -*- - -import sys, os -sys.path.append(os.path.join(os.path.dirname(__file__), '..')) - -from docscrape import NumpyDocString, FunctionDoc -from docscrape_sphinx import SphinxDocString -from nose.tools import * - -doc_txt = '''\ - numpy.multivariate_normal(mean, cov, shape=None) - - Draw values from a multivariate normal distribution with specified - mean and covariance. - - The multivariate normal or Gaussian distribution is a generalisation - of the one-dimensional normal distribution to higher dimensions. - - Parameters - ---------- - mean : (N,) ndarray - Mean of the N-dimensional distribution. - - .. math:: - - (1+2+3)/3 - - cov : (N,N) ndarray - Covariance matrix of the distribution. - shape : tuple of ints - Given a shape of, for example, (m,n,k), m*n*k samples are - generated, and packed in an m-by-n-by-k arrangement. Because - each sample is N-dimensional, the output shape is (m,n,k,N). - - Returns - ------- - out : ndarray - The drawn samples, arranged according to `shape`. If the - shape given is (m,n,...), then the shape of `out` is is - (m,n,...,N). - - In other words, each entry ``out[i,j,...,:]`` is an N-dimensional - value drawn from the distribution. - - Warnings - -------- - Certain warnings apply. - - Notes - ----- - - Instead of specifying the full covariance matrix, popular - approximations include: - - - Spherical covariance (`cov` is a multiple of the identity matrix) - - Diagonal covariance (`cov` has non-negative elements only on the diagonal) - - This geometrical property can be seen in two dimensions by plotting - generated data-points: - - >>> mean = [0,0] - >>> cov = [[1,0],[0,100]] # diagonal covariance, points lie on x or y-axis - - >>> x,y = multivariate_normal(mean,cov,5000).T - >>> plt.plot(x,y,'x'); plt.axis('equal'); plt.show() - - Note that the covariance matrix must be symmetric and non-negative - definite. - - References - ---------- - .. [1] A. Papoulis, "Probability, Random Variables, and Stochastic - Processes," 3rd ed., McGraw-Hill Companies, 1991 - .. [2] R.O. Duda, P.E. Hart, and D.G. Stork, "Pattern Classification," - 2nd ed., Wiley, 2001. - - See Also - -------- - some, other, funcs - otherfunc : relationship - - Examples - -------- - >>> mean = (1,2) - >>> cov = [[1,0],[1,0]] - >>> x = multivariate_normal(mean,cov,(3,3)) - >>> print x.shape - (3, 3, 2) - - The following is probably true, given that 0.6 is roughly twice the - standard deviation: - - >>> print list( (x[0,0,:] - mean) < 0.6 ) - [True, True] - - .. index:: random - :refguide: random;distributions, random;gauss - - ''' -doc = NumpyDocString(doc_txt) - - -def test_signature(): - assert doc['Signature'].startswith('numpy.multivariate_normal(') - assert doc['Signature'].endswith('shape=None)') - -def test_summary(): - assert doc['Summary'][0].startswith('Draw values') - assert doc['Summary'][-1].endswith('covariance.') - -def test_extended_summary(): - assert doc['Extended Summary'][0].startswith('The multivariate normal') - -def test_parameters(): - assert_equal(len(doc['Parameters']), 3) - assert_equal([n for n,_,_ in doc['Parameters']], ['mean','cov','shape']) - - arg, arg_type, desc = doc['Parameters'][1] - assert_equal(arg_type, '(N,N) ndarray') - assert desc[0].startswith('Covariance matrix') - assert doc['Parameters'][0][-1][-2] == ' (1+2+3)/3' - -def test_returns(): - assert_equal(len(doc['Returns']), 1) - arg, arg_type, desc = doc['Returns'][0] - assert_equal(arg, 'out') - assert_equal(arg_type, 'ndarray') - assert desc[0].startswith('The drawn samples') - assert desc[-1].endswith('distribution.') - -def test_notes(): - assert doc['Notes'][0].startswith('Instead') - assert doc['Notes'][-1].endswith('definite.') - assert_equal(len(doc['Notes']), 17) - -def test_references(): - assert doc['References'][0].startswith('..') - assert doc['References'][-1].endswith('2001.') - -def test_examples(): - assert doc['Examples'][0].startswith('>>>') - assert doc['Examples'][-1].endswith('True]') - -def test_index(): - assert_equal(doc['index']['default'], 'random') - print doc['index'] - assert_equal(len(doc['index']), 2) - assert_equal(len(doc['index']['refguide']), 2) - -def non_blank_line_by_line_compare(a,b): - a = [l for l in a.split('\n') if l.strip()] - b = [l for l in b.split('\n') if l.strip()] - for n,line in enumerate(a): - if not line == b[n]: - raise AssertionError("Lines %s of a and b differ: " - "\n>>> %s\n<<< %s\n" % - (n,line,b[n])) -def test_str(): - non_blank_line_by_line_compare(str(doc), -"""numpy.multivariate_normal(mean, cov, shape=None) - -Draw values from a multivariate normal distribution with specified -mean and covariance. - -The multivariate normal or Gaussian distribution is a generalisation -of the one-dimensional normal distribution to higher dimensions. - -Parameters ----------- -mean : (N,) ndarray - Mean of the N-dimensional distribution. - - .. math:: - - (1+2+3)/3 - -cov : (N,N) ndarray - Covariance matrix of the distribution. -shape : tuple of ints - Given a shape of, for example, (m,n,k), m*n*k samples are - generated, and packed in an m-by-n-by-k arrangement. Because - each sample is N-dimensional, the output shape is (m,n,k,N). - -Returns -------- -out : ndarray - The drawn samples, arranged according to `shape`. If the - shape given is (m,n,...), then the shape of `out` is is - (m,n,...,N). - - In other words, each entry ``out[i,j,...,:]`` is an N-dimensional - value drawn from the distribution. - -Warnings --------- -Certain warnings apply. - -See Also --------- -`some`_, `other`_, `funcs`_ - -`otherfunc`_ - relationship - -Notes ------ -Instead of specifying the full covariance matrix, popular -approximations include: - - - Spherical covariance (`cov` is a multiple of the identity matrix) - - Diagonal covariance (`cov` has non-negative elements only on the diagonal) - -This geometrical property can be seen in two dimensions by plotting -generated data-points: - ->>> mean = [0,0] ->>> cov = [[1,0],[0,100]] # diagonal covariance, points lie on x or y-axis - ->>> x,y = multivariate_normal(mean,cov,5000).T ->>> plt.plot(x,y,'x'); plt.axis('equal'); plt.show() - -Note that the covariance matrix must be symmetric and non-negative -definite. - -References ----------- -.. [1] A. Papoulis, "Probability, Random Variables, and Stochastic - Processes," 3rd ed., McGraw-Hill Companies, 1991 -.. [2] R.O. Duda, P.E. Hart, and D.G. Stork, "Pattern Classification," - 2nd ed., Wiley, 2001. - -Examples --------- ->>> mean = (1,2) ->>> cov = [[1,0],[1,0]] ->>> x = multivariate_normal(mean,cov,(3,3)) ->>> print x.shape -(3, 3, 2) - -The following is probably true, given that 0.6 is roughly twice the -standard deviation: - ->>> print list( (x[0,0,:] - mean) < 0.6 ) -[True, True] - -.. index:: random - :refguide: random;distributions, random;gauss""") - - -def test_sphinx_str(): - sphinx_doc = SphinxDocString(doc_txt) - non_blank_line_by_line_compare(str(sphinx_doc), -""" -.. index:: random - single: random;distributions, random;gauss - -Draw values from a multivariate normal distribution with specified -mean and covariance. - -The multivariate normal or Gaussian distribution is a generalisation -of the one-dimensional normal distribution to higher dimensions. - -:Parameters: - - **mean** : (N,) ndarray - - Mean of the N-dimensional distribution. - - .. math:: - - (1+2+3)/3 - - **cov** : (N,N) ndarray - - Covariance matrix of the distribution. - - **shape** : tuple of ints - - Given a shape of, for example, (m,n,k), m*n*k samples are - generated, and packed in an m-by-n-by-k arrangement. Because - each sample is N-dimensional, the output shape is (m,n,k,N). - -:Returns: - - **out** : ndarray - - The drawn samples, arranged according to `shape`. If the - shape given is (m,n,...), then the shape of `out` is is - (m,n,...,N). - - In other words, each entry ``out[i,j,...,:]`` is an N-dimensional - value drawn from the distribution. - -.. warning:: - - Certain warnings apply. - -.. seealso:: - - :obj:`some`, :obj:`other`, :obj:`funcs` - - :obj:`otherfunc` - relationship - -.. rubric:: Notes - -Instead of specifying the full covariance matrix, popular -approximations include: - - - Spherical covariance (`cov` is a multiple of the identity matrix) - - Diagonal covariance (`cov` has non-negative elements only on the diagonal) - -This geometrical property can be seen in two dimensions by plotting -generated data-points: - ->>> mean = [0,0] ->>> cov = [[1,0],[0,100]] # diagonal covariance, points lie on x or y-axis - ->>> x,y = multivariate_normal(mean,cov,5000).T ->>> plt.plot(x,y,'x'); plt.axis('equal'); plt.show() - -Note that the covariance matrix must be symmetric and non-negative -definite. - -.. rubric:: References - -.. [1] A. Papoulis, "Probability, Random Variables, and Stochastic - Processes," 3rd ed., McGraw-Hill Companies, 1991 -.. [2] R.O. Duda, P.E. Hart, and D.G. Stork, "Pattern Classification," - 2nd ed., Wiley, 2001. - -.. rubric:: Examples - ->>> mean = (1,2) ->>> cov = [[1,0],[1,0]] ->>> x = multivariate_normal(mean,cov,(3,3)) ->>> print x.shape -(3, 3, 2) - -The following is probably true, given that 0.6 is roughly twice the -standard deviation: - ->>> print list( (x[0,0,:] - mean) < 0.6 ) -[True, True] -""") - - -doc2 = NumpyDocString(""" - Returns array of indices of the maximum values of along the given axis. - - Parameters - ---------- - a : {array_like} - Array to look in. - axis : {None, integer} - If None, the index is into the flattened array, otherwise along - the specified axis""") - -def test_parameters_without_extended_description(): - assert_equal(len(doc2['Parameters']), 2) - -doc3 = NumpyDocString(""" - my_signature(*params, **kwds) - - Return this and that. - """) - -def test_escape_stars(): - signature = str(doc3).split('\n')[0] - assert_equal(signature, 'my_signature(\*params, \*\*kwds)') - -doc4 = NumpyDocString( - """a.conj() - - Return an array with all complex-valued elements conjugated.""") - -def test_empty_extended_summary(): - assert_equal(doc4['Extended Summary'], []) - -doc5 = NumpyDocString( - """ - a.something() - - Raises - ------ - LinAlgException - If array is singular. - - """) - -def test_raises(): - assert_equal(len(doc5['Raises']), 1) - name,_,desc = doc5['Raises'][0] - assert_equal(name,'LinAlgException') - assert_equal(desc,['If array is singular.']) - -def test_see_also(): - doc6 = NumpyDocString( - """ - z(x,theta) - - See Also - -------- - func_a, func_b, func_c - func_d : some equivalent func - foo.func_e : some other func over - multiple lines - func_f, func_g, :meth:`func_h`, func_j, - func_k - :obj:`baz.obj_q` - :class:`class_j`: fubar - foobar - """) - - assert len(doc6['See Also']) == 12 - for func, desc, role in doc6['See Also']: - if func in ('func_a', 'func_b', 'func_c', 'func_f', - 'func_g', 'func_h', 'func_j', 'func_k', 'baz.obj_q'): - assert(not desc) - else: - assert(desc) - - if func == 'func_h': - assert role == 'meth' - elif func == 'baz.obj_q': - assert role == 'obj' - elif func == 'class_j': - assert role == 'class' - else: - assert role is None - - if func == 'func_d': - assert desc == ['some equivalent func'] - elif func == 'foo.func_e': - assert desc == ['some other func over', 'multiple lines'] - elif func == 'class_j': - assert desc == ['fubar', 'foobar'] - -def test_see_also_print(): - class Dummy(object): - """ - See Also - -------- - func_a, func_b - func_c : some relationship - goes here - func_d - """ - pass - - obj = Dummy() - s = str(FunctionDoc(obj, role='func')) - assert(':func:`func_a`, :func:`func_b`' in s) - assert(' some relationship' in s) - assert(':func:`func_d`' in s) - -doc7 = NumpyDocString(""" - - Doc starts on second line. - - """) - -def test_empty_first_line(): - assert doc7['Summary'][0].startswith('Doc starts') - - -def test_no_summary(): - str(SphinxDocString(""" - Parameters - ----------""")) - - -def test_unicode(): - doc = SphinxDocString(""" - öäöäöäöäöåååå - - öäöäöäööäååå - - Parameters - ---------- - ååå : äää - ööö - - Returns - ------- - ååå : ööö - äää - - """) - assert doc['Summary'][0] == u'öäöäöäöäöåååå'.encode('utf-8') diff --git a/examples/README b/examples/README new file mode 100644 index 00000000..77d9bed6 --- /dev/null +++ b/examples/README @@ -0,0 +1,2 @@ +Here are various example files for configuration of routes and gae. +To use them, move them to main web2py folder and customize them. \ No newline at end of file diff --git a/app.example.yaml b/examples/app.example.yaml similarity index 100% rename from app.example.yaml rename to examples/app.example.yaml diff --git a/appengine_config.example.py b/examples/appengine_config.example.py similarity index 100% rename from appengine_config.example.py rename to examples/appengine_config.example.py diff --git a/logging.example.conf b/examples/logging.example.conf similarity index 100% rename from logging.example.conf rename to examples/logging.example.conf diff --git a/queue.example.yaml b/examples/queue.example.yaml similarity index 100% rename from queue.example.yaml rename to examples/queue.example.yaml diff --git a/router.example.py b/examples/router.example.py similarity index 100% rename from router.example.py rename to examples/router.example.py diff --git a/routes.example.py b/examples/routes.example.py similarity index 100% rename from routes.example.py rename to examples/routes.example.py diff --git a/setup_app.py b/extras/build_web2py/setup_app.py similarity index 100% rename from setup_app.py rename to extras/build_web2py/setup_app.py diff --git a/setup_exe.conf b/extras/build_web2py/setup_exe.conf similarity index 100% rename from setup_exe.conf rename to extras/build_web2py/setup_exe.conf diff --git a/setup_exe.py b/extras/build_web2py/setup_exe.py similarity index 100% rename from setup_exe.py rename to extras/build_web2py/setup_exe.py diff --git a/epydoc.conf b/extras/epydoc/epydoc.conf similarity index 96% rename from epydoc.conf rename to extras/epydoc/epydoc.conf index 89c60bc2..d0107009 100755 --- a/epydoc.conf +++ b/extras/epydoc/epydoc.conf @@ -77,7 +77,7 @@ name: web2py Web Framework # The CSS stylesheet for HTML output. Can be the name of a built-in # stylesheet, or the name of a file. -css: epydoc.css +css: extras/epydoc/epydoc.css # The documented project's URL. url: http://www.web2py.com diff --git a/epydoc.css b/extras/epydoc/epydoc.css similarity index 100% rename from epydoc.css rename to extras/epydoc/epydoc.css diff --git a/splashlogo.gif b/extras/icons/splashlogo.gif similarity index 100% rename from splashlogo.gif rename to extras/icons/splashlogo.gif diff --git a/web2py.gif b/extras/icons/web2py.gif similarity index 100% rename from web2py.gif rename to extras/icons/web2py.gif diff --git a/web2py.icns b/extras/icons/web2py.icns similarity index 100% rename from web2py.icns rename to extras/icons/web2py.icns diff --git a/web2py.ico b/extras/icons/web2py.ico similarity index 100% rename from web2py.ico rename to extras/icons/web2py.ico diff --git a/gluon/widget.py b/gluon/widget.py index 1ba8224a..bb13cda6 100644 --- a/gluon/widget.py +++ b/gluon/widget.py @@ -151,7 +151,7 @@ def presentation(root): canvas.pack() root.update() - logo = 'splashlogo.gif' + logo = 'extras/icons/splashlogo.gif' if os.path.exists(logo): img = Tkinter.PhotoImage(file=logo) pnl = Tkinter.Label(canvas, image=img, background='white', bd=0) @@ -199,7 +199,7 @@ class web2pyDialog(object): self.menu = Tkinter.Menu(self.root) servermenu = Tkinter.Menu(self.menu, tearoff=0) httplog = os.path.join(self.options.folder, 'httpserver.log') - iconphoto = 'web2py.gif' + iconphoto = 'extras/icons/web2py.gif' if os.path.exists(iconphoto): img = Tkinter.PhotoImage(file=iconphoto) self.root.tk.call('wm', 'iconphoto', self.root._w, img) diff --git a/mkweb2pyenv b/mkweb2pyenv deleted file mode 100755 index 6c01920d..00000000 --- a/mkweb2pyenv +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env python -import gluon -from gluon.fileutils import untar -import os -import sys - - -def main(): - path = gluon.__path__ - out_path = os.getcwd() - try: - if sys.argv[1] and os.path.exists(sys.argv[1]):# To untar the web2py env to the selected path - out_path = sys.argv[1] - else: - os.mkdir(sys.argv[1]) - out_path = sys.argv[1] - except: - pass - try: - print "Creating a web2py env in: " + out_path - untar(os.path.join(path[0],'env.tar'),out_path) - except: - print "Failed to create the web2py env" - print "Please reinstall web2py from pip" - -if __name__ == '__main__': - main() diff --git a/runweb2py b/runweb2py deleted file mode 100644 index 48fe9afc..00000000 --- a/runweb2py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -import os -import sys - -path = os.getcwd() -try: - if sys.argv[1] and os.path.exists(sys.argv[1]): - path = sys.argv[1] -except: - pass - -os.chdir(path) -sys.path = [path]+[p for p in sys.path if not p==path] -# import gluon.import_all ##### This should be uncommented for py2exe.py -import gluon.widget - -def main(): - # Start Web2py and Web2py cron service! - gluon.widget.start(cron=True) - -if __name__ == '__main__': - main() diff --git a/storage.sqlite b/storage.sqlite deleted file mode 100644 index e69de29b..00000000 diff --git a/w2p_apps b/w2p_apps deleted file mode 100755 index 6c01920d..00000000 --- a/w2p_apps +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env python -import gluon -from gluon.fileutils import untar -import os -import sys - - -def main(): - path = gluon.__path__ - out_path = os.getcwd() - try: - if sys.argv[1] and os.path.exists(sys.argv[1]):# To untar the web2py env to the selected path - out_path = sys.argv[1] - else: - os.mkdir(sys.argv[1]) - out_path = sys.argv[1] - except: - pass - try: - print "Creating a web2py env in: " + out_path - untar(os.path.join(path[0],'env.tar'),out_path) - except: - print "Failed to create the web2py env" - print "Please reinstall web2py from pip" - -if __name__ == '__main__': - main() diff --git a/w2p_clone b/w2p_clone deleted file mode 100755 index 8d8c392d..00000000 --- a/w2p_clone +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env python -import os -import sys - -""" -Author: Christopher Steel on behalf of Voice of Access -Copyright: Copyrighted (c) by Massimo Di Pierro (2007-2013) - -web2py_clone becomes part of the web2py distribution available -on Pypi via 'pip install web2py' - -web2py_clone is one of multiple commands that become available after running -'pip install web2py' in a virtual environment. It requires -mercurial to be installed in the virtual environment. - -web2py_clone creates a local clone from the Web2py google code -project in the directory "./web2py," a directory called web2py -one directory up from the location of this script. - -./bin/web2py_clone -./web2py -""" - - -def main(): - iwd = cwd = os.getcwd() # set initial and current working directories - script_filename = os.path.realpath(__file__) - script_dirname = os.path.dirname(script_filename) - try: - print ("cwd now: %s" % cwd) - except: - print ("command failed %s" % cwd) - try: - os.chdir(script_dirname) - cwd = os.getcwd() - print ("cwd now: %s" % cwd) - source = "https://code.google.com/p/web2py/" - target = os.path.join('..','web2py') - print ("attempting to clone %s" % source) - print ("to %s" % target) - if os.path.isdir(target): - print ("found directory called web2py at %s" % target) - print ("is web2py already installed?") - print ("aborting clone attempt") - else: - os.system("hg clone %s %s" % (source,target)) - os.chdir(iwd) # return to our initial working directory - cwd = iwd # set current working directory - - except: - print ("web2py-clone failed in second try statement %s" % cwd) - -if __name__ == '__main__': - main() - diff --git a/w2p_run b/w2p_run deleted file mode 100755 index 48fe9afc..00000000 --- a/w2p_run +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -import os -import sys - -path = os.getcwd() -try: - if sys.argv[1] and os.path.exists(sys.argv[1]): - path = sys.argv[1] -except: - pass - -os.chdir(path) -sys.path = [path]+[p for p in sys.path if not p==path] -# import gluon.import_all ##### This should be uncommented for py2exe.py -import gluon.widget - -def main(): - # Start Web2py and Web2py cron service! - gluon.widget.start(cron=True) - -if __name__ == '__main__': - main()