[med-svn] [python-mne] 35/376: adding auto examples to doc
Yaroslav Halchenko
debian at onerussian.com
Fri Nov 27 17:22:02 UTC 2015
This is an automated email from the git hooks/post-receive script.
yoh pushed a commit to annotated tag v0.1
in repository python-mne.
commit 7738cc523ae6113badd8a7d044068e462dee8a99
Author: Alexandre Gramfort <alexandre.gramfort at inria.fr>
Date: Tue Jan 18 12:22:35 2011 -0500
adding auto examples to doc
---
.gitignore | 21 +
README.rst | 10 +-
doc/Makefile | 4 +-
doc/source/conf.py | 40 +-
doc/source/config_doc.rst | 2 +-
doc/source/contents.rst | 2 +-
doc/source/getting_started.rst | 4 +-
doc/source/index.rst | 14 +-
doc/sphinxext/gen_rst.py | 186 +++++++++
doc/sphinxext/numpy_ext/__init__.py | 0
doc/sphinxext/numpy_ext/docscrape.py | 498 ++++++++++++++++++++++++
doc/sphinxext/numpy_ext/docscrape_sphinx.py | 226 +++++++++++
doc/sphinxext/numpy_ext/numpydoc.py | 164 ++++++++
doc/sphinxext/numpy_ext_old/__init__.py | 0
doc/sphinxext/numpy_ext_old/docscrape.py | 492 +++++++++++++++++++++++
doc/sphinxext/numpy_ext_old/docscrape_sphinx.py | 133 +++++++
doc/sphinxext/{ => numpy_ext_old}/numpydoc.py | 15 +-
examples/README.txt | 6 +
examples/compute_mne_inverse.py | 5 +-
examples/read_bem_surfaces.py | 5 +-
examples/read_cov.py | 5 +-
examples/read_epochs.py | 5 +-
examples/read_events.py | 5 +-
examples/read_evoked.py | 6 +-
examples/read_forward.py | 5 +-
examples/read_inverse.py | 5 +-
examples/read_raw.py | 5 +-
examples/read_stc.py | 5 +-
examples/read_write_raw.py | 5 +-
29 files changed, 1823 insertions(+), 50 deletions(-)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..02b9aba
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,21 @@
+*.pyc
+*.so
+*.fif
+*.tar.gz
+*.log
+*.stc
+*~
+.#*
+*.swp
+build
+
+dist/
+doc/_build/
+doc/build/
+doc/auto_examples/
+doc/modules/generated/
+pip-log.txt
+.coverage
+tags
+doc/coverages
+doc/samples
diff --git a/README.rst b/README.rst
index 40506e1..cc85dde 100644
--- a/README.rst
+++ b/README.rst
@@ -3,7 +3,15 @@
About
=====
-MNE is a python module for processing MEG and EEG data;
+MNE is a python module for processing MEG and EEG data.
+
+It is a project funded by:
+
+Athinoula A. Martinos Center for Biomedical Imaging
+Massachusetts General Hospital
+Charlestown, MA, USA
+
+Available under the BSD license.
It is mainly a reimplementation of the Matlab code written by Matti Hämäläinen.
diff --git a/doc/Makefile b/doc/Makefile
index 267fbf0..6c3c1ab 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -60,9 +60,9 @@ qthelp:
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in build/qthelp, like this:"
- @echo "# qcollectiongenerator build/qthelp/PyFIFF.qhcp"
+ @echo "# qcollectiongenerator build/qthelp/MNE.qhcp"
@echo "To view the help file:"
- @echo "# assistant -collectionFile build/qthelp/PyFIFF.qhc"
+ @echo "# assistant -collectionFile build/qthelp/MNE.qhc"
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) build/latex
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 3645e0a..da9d454 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
-# PyFIFF documentation build configuration file, created by
+# MNE documentation build configuration file, created by
# sphinx-quickstart on Fri Jun 11 10:45:48 2010.
#
# This file is execfile()d with the current directory set to its containing dir.
@@ -16,22 +16,29 @@ 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('../fiff'))
+sys.path.append(os.path.abspath('../mne'))
sys.path.append(os.path.abspath('../sphinxext'))
-import fiff
+import mne
# -- 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.todo',
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.autosummary',
'sphinx.ext.pngmath',
- 'sphinx.ext.inheritance_diagram',
- 'ipython_console_highlighting',
- 'only_directives']
+ 'gen_rst']
+
+try:
+ import numpy_ext.numpydoc
+ extensions.append('numpy_ext.numpydoc')
+ # With older versions of sphinx, this causes a crash
+ autosummary_generate = True
+except:
+ # Older version of sphinx
+ extensions.append('numpy_ext_old.numpydoc')
+
+autodoc_default_flags=['inherited-members']
# extensions = ['sphinx.ext.autodoc',
# 'sphinx.ext.doctest',
@@ -51,19 +58,22 @@ source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8'
+# Generate the plots for the gallery
+plot_gallery = True
+
# The master toctree document.
master_doc = 'index'
# General information about the project.
-project = u'PyFIFF'
-copyright = u'2010, Alexandre Gramfort'
+project = u'MNE'
+copyright = u'2011, Alexandre Gramfort'
# 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.
#
# The short X.Y version.
-version = fiff.__version__
+version = mne.__version__
# The full version, including alpha/beta/rc tags.
release = version
@@ -102,7 +112,7 @@ exclude_trees = ['_build']
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
-modindex_common_prefix = ['fiff.']
+modindex_common_prefix = ['mne.']
# -- Options for HTML output ---------------------------------------------------
@@ -176,7 +186,7 @@ html_use_index = True
#html_file_suffix = ''
# Output file base name for HTML help builder.
-htmlhelp_basename = 'PyFIFFdoc'
+htmlhelp_basename = 'mne-doc'
# -- Options for LaTeX output --------------------------------------------------
@@ -190,7 +200,7 @@ htmlhelp_basename = 'PyFIFFdoc'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
- ('index', 'PyFIFF.tex', u'PyFIFF Documentation',
+ ('index', 'MNE.tex', u'MNE Python Documentation',
u'Alexandre Gramfort', 'manual'),
]
diff --git a/doc/source/config_doc.rst b/doc/source/config_doc.rst
index 0f6db6a..e391493 100644
--- a/doc/source/config_doc.rst
+++ b/doc/source/config_doc.rst
@@ -1,6 +1,6 @@
.. _config_doc:
-This is a skeleton config file for the PyFIFF package.
+This is a skeleton config file for the MNE package.
See the documentation at http://XXX
diff --git a/doc/source/contents.rst b/doc/source/contents.rst
index f0a0639..b2e5aa7 100644
--- a/doc/source/contents.rst
+++ b/doc/source/contents.rst
@@ -8,4 +8,4 @@ Documentation Contents
:maxdepth: 2
getting_started.rst
- tutorial.rst
+ auto_examples/index.rst
diff --git a/doc/source/getting_started.rst b/doc/source/getting_started.rst
index b55bc31..cdc7495 100644
--- a/doc/source/getting_started.rst
+++ b/doc/source/getting_started.rst
@@ -3,7 +3,7 @@
Getting Started
===============
-PyFIFF is written in pure Python making it easy to setup of
+MNE is written in pure Python making it easy to setup of
any machine with Python >=2.4, Numpy >= 1.1 and Scipy >= 0.6.
To test that everything worked properly, open up IPython::
@@ -14,7 +14,7 @@ Although all of the examples in this documentation are in the style
of the standard Python interpreter, the use of IPython is highly
recommended. Then type::
- >>> import fiff
+ >>> import mne
If you get a new prompt with no error messages, you should be good to go.
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 1a7660f..2a6fe1a 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -1,10 +1,12 @@
-===========
-PyFIFF Home
-===========
+========
+MNE Home
+========
-PyFIFF is a Python package for reading and writing FIF files
-produces by Neuromag MEG systems. PyFIFF offers an neat
-interaction with outputs provided by MNE:
+MNE is a Python package for processing electro-encephalography (EEG)
+and magneto-encephalography data (MEG). It includes python code for
+reading and writing FIF files produces by Neuromag MEG systems.
+
+This python package is tightly linked the MNE project:
* `MNE's <http://www.nmr.mgh.harvard.edu/martinos/userInfo/data/sofMNE.php>`
diff --git a/doc/sphinxext/gen_rst.py b/doc/sphinxext/gen_rst.py
new file mode 100644
index 0000000..a923171
--- /dev/null
+++ b/doc/sphinxext/gen_rst.py
@@ -0,0 +1,186 @@
+"""
+Example generation for the scikit learn
+
+Generate the rst files for the examples by iterating over the python
+example files.
+
+Files that generate images should start with 'plot'
+
+"""
+import os
+import shutil
+import traceback
+
+fileList = []
+
+import matplotlib
+matplotlib.use('Agg')
+
+import token, tokenize
+
+rst_template = """
+
+.. _example_%(short_fname)s:
+
+%(docstring)s
+
+**Python source code:** :download:`%(fname)s <%(fname)s>`
+
+.. literalinclude:: %(fname)s
+ :lines: %(end_row)s-
+ """
+
+plot_rst_template = """
+
+.. _example_%(short_fname)s:
+
+%(docstring)s
+
+.. image:: images/%(image_name)s
+ :align: center
+
+**Python source code:** :download:`%(fname)s <%(fname)s>`
+
+.. literalinclude:: %(fname)s
+ :lines: %(end_row)s-
+ """
+
+
+def extract_docstring(filename):
+ """ Extract a module-level docstring, if any
+ """
+ lines = file(filename).readlines()
+ start_row = 0
+ if lines[0].startswith('#!'):
+ lines.pop(0)
+ start_row = 1
+
+ docstring = ''
+ first_par = ''
+ tokens = tokenize.generate_tokens(lines.__iter__().next)
+ for tok_type, tok_content, _, (erow, _), _ in tokens:
+ tok_type = token.tok_name[tok_type]
+ if tok_type in ('NEWLINE', 'COMMENT', 'NL', 'INDENT', 'DEDENT'):
+ continue
+ elif tok_type == 'STRING':
+ docstring = eval(tok_content)
+ # If the docstring is formatted with several paragraphs, extract
+ # the first one:
+ paragraphs = '\n'.join(line.rstrip()
+ for line in docstring.split('\n')).split('\n\n')
+ if len(paragraphs) > 0:
+ first_par = paragraphs[0]
+ break
+ return docstring, first_par, erow+1+start_row
+
+
+def generate_example_rst(app):
+ """ Generate the list of examples, as well as the contents of
+ examples.
+ """
+ root_dir = os.path.join(app.builder.srcdir, 'auto_examples')
+ example_dir = os.path.abspath(app.builder.srcdir + '/../../' + 'examples')
+ try:
+ plot_gallery = eval(app.builder.config.plot_gallery)
+ except TypeError:
+ plot_gallery = bool(app.builder.config.plot_gallery)
+ if not os.path.exists(example_dir):
+ os.makedirs(example_dir)
+ if not os.path.exists(root_dir):
+ os.makedirs(root_dir)
+
+ # we create an index.rst with all examples
+ fhindex = file(os.path.join(root_dir, 'index.rst'), 'w')
+ fhindex.write("""\
+
+Examples
+========
+
+.. _examples-index:
+""")
+ # Here we don't use an os.walk, but we recurse only twice: flat is
+ # better than nested.
+ generate_dir_rst('.', fhindex, example_dir, root_dir, plot_gallery)
+ for dir in sorted(os.listdir(example_dir)):
+ if dir == '.svn':
+ continue
+ if os.path.isdir(os.path.join(example_dir, dir)):
+ generate_dir_rst(dir, fhindex, example_dir, root_dir, plot_gallery)
+ fhindex.flush()
+
+
+def generate_dir_rst(dir, fhindex, example_dir, root_dir, plot_gallery):
+ """ Generate the rst file for an example directory.
+ """
+ target_dir = os.path.join(root_dir, dir)
+ src_dir = os.path.join(example_dir, dir)
+ if not os.path.exists(os.path.join(src_dir, 'README.txt')):
+ print 80*'_'
+ print ('Example directory %s does not have a README.txt file'
+ % src_dir)
+ print 'Skipping this directory'
+ print 80*'_'
+ return
+ fhindex.write("""
+
+%s
+
+.. toctree::
+
+""" % file(os.path.join(src_dir, 'README.txt')).read())
+ if not os.path.exists(target_dir):
+ os.makedirs(target_dir)
+ for fname in sorted(os.listdir(src_dir)):
+ if fname.endswith('py'):
+ generate_file_rst(fname, target_dir, src_dir, plot_gallery)
+ fhindex.write(' %s\n' % (os.path.join(dir, fname[:-3])))
+
+
+def generate_file_rst(fname, target_dir, src_dir, plot_gallery):
+ """ Generate the rst file for a given example.
+ """
+ image_name = fname[:-2] + 'png'
+ global rst_template, plot_rst_template
+ this_template = rst_template
+ last_dir = os.path.split(src_dir)[-1]
+ # to avoid leading . in file names
+ if last_dir == '.': last_dir = ''
+ else: last_dir += '_'
+ short_fname = last_dir + fname
+ src_file = os.path.join(src_dir, fname)
+ example_file = os.path.join(target_dir, fname)
+ shutil.copyfile(src_file, example_file)
+ if plot_gallery and fname.startswith('plot'):
+ # generate the plot as png image if file name
+ # starts with plot and if it is more recent than an
+ # existing image.
+ if not os.path.exists(
+ os.path.join(target_dir, 'images')):
+ os.makedirs(os.path.join(target_dir, 'images'))
+ image_file = os.path.join(target_dir, 'images', image_name)
+ if (not os.path.exists(image_file) or
+ os.stat(image_file).st_mtime <=
+ os.stat(src_file).st_mtime):
+ print 'plotting %s' % fname
+ import matplotlib.pyplot as plt
+ plt.close('all')
+ try:
+ execfile(example_file, {'pl' : plt})
+ plt.savefig(image_file)
+ except:
+ print 80*'_'
+ print '%s is not compiling:' % fname
+ traceback.print_exc()
+ print 80*'_'
+ this_template = plot_rst_template
+
+ docstring, short_desc, end_row = extract_docstring(example_file)
+
+ f = open(os.path.join(target_dir, fname[:-2] + 'rst'),'w')
+ f.write( this_template % locals())
+ f.flush()
+
+
+def setup(app):
+ app.connect('builder-inited', generate_example_rst)
+ app.add_config_value('plot_gallery', True, 'html')
diff --git a/doc/sphinxext/numpy_ext/__init__.py b/doc/sphinxext/numpy_ext/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/doc/sphinxext/numpy_ext/docscrape.py b/doc/sphinxext/numpy_ext/docscrape.py
new file mode 100644
index 0000000..ad5998c
--- /dev/null
+++ b/doc/sphinxext/numpy_ext/docscrape.py
@@ -0,0 +1,498 @@
+"""Extract reference documentation from the NumPy source tree.
+
+"""
+
+import inspect
+import textwrap
+import re
+import pydoc
+from StringIO import StringIO
+from warnings import warn
+
+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, config={}):
+ 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<role>\w+):`(?P<name>[a-zA-Z0-9_.-]+)`|"
+ r" (?P<name2>[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)
+ for param_list in ('Attributes', 'Methods'):
+ out += self._str_param_list(param_list)
+ 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, config={}):
+ self._f = func
+ self._role = role # e.g. "func" or "meth"
+
+ if doc is None:
+ if func is None:
+ raise ValueError("No function or docstring given")
+ doc = inspect.getdoc(func) or ''
+ NumpyDocString.__init__(self, doc)
+
+ if not self['Signature'] and func is not None:
+ 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, doc=None, modulename='', func_doc=FunctionDoc,
+ config={}):
+ if not inspect.isclass(cls) and cls is not None:
+ raise ValueError("Expected a class or None, but got %r" % cls)
+ self._cls = cls
+
+ if modulename and not modulename.endswith('.'):
+ modulename += '.'
+ self._mod = modulename
+
+ if doc is None:
+ if cls is None:
+ raise ValueError("No class or documentation string given")
+ doc = pydoc.getdoc(cls)
+
+ NumpyDocString.__init__(self, doc)
+
+ if config.get('show_class_members', True):
+ if not self['Methods']:
+ self['Methods'] = [(name, '', '')
+ for name in sorted(self.methods)]
+ if not self['Attributes']:
+ self['Attributes'] = [(name, '', '')
+ for name in sorted(self.properties)]
+
+ @property
+ def methods(self):
+ if self._cls is None:
+ return []
+ return [name for name,func in inspect.getmembers(self._cls)
+ if not name.startswith('_') and callable(func)]
+
+ @property
+ def properties(self):
+ if self._cls is None:
+ return []
+ return [name for name,func in inspect.getmembers(self._cls)
+ if not name.startswith('_') and func is None]
diff --git a/doc/sphinxext/numpy_ext/docscrape_sphinx.py b/doc/sphinxext/numpy_ext/docscrape_sphinx.py
new file mode 100644
index 0000000..9f4350d
--- /dev/null
+++ b/doc/sphinxext/numpy_ext/docscrape_sphinx.py
@@ -0,0 +1,226 @@
+import re, inspect, textwrap, pydoc
+import sphinx
+from docscrape import NumpyDocString, FunctionDoc, ClassDoc
+
+class SphinxDocString(NumpyDocString):
+ def __init__(self, docstring, config={}):
+ self.use_plots = config.get('use_plots', False)
+ NumpyDocString.__init__(self, docstring, config=config)
+
+ # 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
+
+ @property
+ def _obj(self):
+ if hasattr(self, '_cls'):
+ return self._cls
+ elif hasattr(self, '_f'):
+ return self._f
+ return None
+
+ def _str_member_list(self, name):
+ """
+ Generate a member listing, autosummary:: table where possible,
+ and a table where not.
+
+ """
+ out = []
+ if self[name]:
+ out += ['.. rubric:: %s' % name, '']
+ prefix = getattr(self, '_name', '')
+
+ if prefix:
+ prefix = '~%s.' % prefix
+
+ autosum = []
+ others = []
+ for param, param_type, desc in self[name]:
+ param = param.strip()
+ if not self._obj or hasattr(self._obj, param):
+ autosum += [" %s%s" % (prefix, param)]
+ else:
+ others.append((param, param_type, desc))
+
+ if autosum:
+ out += ['.. autosummary::', ' :toctree:', '']
+ out += autosum
+
+ if others:
+ maxlen_0 = max([len(x[0]) for x in others])
+ maxlen_1 = max([len(x[1]) for x in others])
+ hdr = "="*maxlen_0 + " " + "="*maxlen_1 + " " + "="*10
+ fmt = '%%%ds %%%ds ' % (maxlen_0, maxlen_1)
+ n_indent = maxlen_0 + maxlen_1 + 4
+ out += [hdr]
+ for param, param_type, desc in others:
+ out += [fmt % (param.strip(), param_type)]
+ out += self._str_indent(desc, n_indent)
+ out += [hdr]
+ 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_examples(self):
+ examples_str = "\n".join(self['Examples'])
+
+ if (self.use_plots and 'import matplotlib' in examples_str
+ and 'plot::' not in examples_str):
+ out = []
+ out += self._str_header('Examples')
+ out += ['.. plot::', '']
+ out += self._str_indent(self['Examples'])
+ out += ['']
+ return out
+ else:
+ return self._str_section('Examples')
+
+ 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', '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_examples()
+ for param_list in ('Attributes', 'Methods'):
+ out += self._str_member_list(param_list)
+ out = self._str_indent(out,indent)
+ return '\n'.join(out)
+
+class SphinxFunctionDoc(SphinxDocString, FunctionDoc):
+ def __init__(self, obj, doc=None, config={}):
+ self.use_plots = config.get('use_plots', False)
+ FunctionDoc.__init__(self, obj, doc=doc, config=config)
+
+class SphinxClassDoc(SphinxDocString, ClassDoc):
+ def __init__(self, obj, doc=None, func_doc=None, config={}):
+ self.use_plots = config.get('use_plots', False)
+ ClassDoc.__init__(self, obj, doc=doc, func_doc=None, config=config)
+
+class SphinxObjDoc(SphinxDocString):
+ def __init__(self, obj, doc=None, config={}):
+ self._f = obj
+ SphinxDocString.__init__(self, doc, config=config)
+
+def get_doc_object(obj, what=None, doc=None, config={}):
+ 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,
+ config=config)
+ elif what in ('function', 'method'):
+ return SphinxFunctionDoc(obj, doc=doc, config=config)
+ else:
+ if doc is None:
+ doc = pydoc.getdoc(obj)
+ return SphinxObjDoc(obj, doc, config=config)
diff --git a/doc/sphinxext/numpy_ext/numpydoc.py b/doc/sphinxext/numpy_ext/numpydoc.py
new file mode 100644
index 0000000..aa39005
--- /dev/null
+++ b/doc/sphinxext/numpy_ext/numpydoc.py
@@ -0,0 +1,164 @@
+"""
+========
+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
+from sphinx.util.compat import Directive
+import inspect
+
+def mangle_docstrings(app, what, name, obj, options, lines,
+ reference_offset=[0]):
+
+ cfg = dict(use_plots=app.config.numpydoc_use_plots,
+ show_class_members=app.config.numpydoc_show_class_members)
+
+ if what == 'module':
+ # Strip top title
+ title_re = re.compile(ur'^\s*[#*=]{4,}\n[a-z0-9 -]+\n[#*=]{4,}\s*',
+ re.I|re.S)
+ lines[:] = title_re.sub(u'', u"\n".join(lines)).split(u"\n")
+ else:
+ doc = get_doc_object(obj, what, u"\n".join(lines), config=cfg)
+ lines[:] = unicode(doc).split(u"\n")
+
+ if app.config.numpydoc_edit_link and hasattr(obj, '__name__') and \
+ obj.__name__:
+ if hasattr(obj, '__module__'):
+ v = dict(full_name=u"%s.%s" % (obj.__module__, obj.__name__))
+ else:
+ v = dict(full_name=obj.__name__)
+ lines += [u'', u'.. htmlonly::', '']
+ lines += [u' %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(ur'^.. \[([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(ur'^\d+$', r):
+ new_r = u"R%d" % (reference_offset[0] + int(r))
+ else:
+ new_r = u"%s%d" % (r, reference_offset[0])
+ lines[i] = lines[i].replace(u'[%s]_' % r,
+ u'[%s]_' % new_r)
+ lines[i] = lines[i].replace(u'.. [%s]' % r,
+ u'.. [%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
+ (not hasattr(obj, '__init__') or
+ '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(u"^[^(]*", u"", doc['Signature'])
+ return sig, u''
+
+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('autodoc-process-signature', mangle_signature)
+ app.add_config_value('numpydoc_edit_link', None, False)
+ app.add_config_value('numpydoc_use_plots', None, False)
+ app.add_config_value('numpydoc_show_class_members', True, True)
+
+ # Extra mangling domains
+ app.add_domain(NumpyPythonDomain)
+ app.add_domain(NumpyCDomain)
+
+#------------------------------------------------------------------------------
+# Docstring-mangling domains
+#------------------------------------------------------------------------------
+
+from docutils.statemachine import ViewList
+from sphinx.domains.c import CDomain
+from sphinx.domains.python import PythonDomain
+
+class ManglingDomainBase(object):
+ directive_mangling_map = {}
+
+ def __init__(self, *a, **kw):
+ super(ManglingDomainBase, self).__init__(*a, **kw)
+ self.wrap_mangling_directives()
+
+ def wrap_mangling_directives(self):
+ for name, objtype in self.directive_mangling_map.items():
+ self.directives[name] = wrap_mangling_directive(
+ self.directives[name], objtype)
+
+class NumpyPythonDomain(ManglingDomainBase, PythonDomain):
+ name = 'np'
+ directive_mangling_map = {
+ 'function': 'function',
+ 'class': 'class',
+ 'exception': 'class',
+ 'method': 'function',
+ 'classmethod': 'function',
+ 'staticmethod': 'function',
+ 'attribute': 'attribute',
+ }
+
+class NumpyCDomain(ManglingDomainBase, CDomain):
+ name = 'np-c'
+ directive_mangling_map = {
+ 'function': 'function',
+ 'member': 'attribute',
+ 'macro': 'function',
+ 'type': 'class',
+ 'var': 'object',
+ }
+
+def wrap_mangling_directive(base_directive, objtype):
+ class directive(base_directive):
+ def run(self):
+ env = self.state.document.settings.env
+
+ name = None
+ if self.arguments:
+ m = re.match(r'^(.*\s+)?(.*?)(\(.*)?', self.arguments[0])
+ name = m.group(2).strip()
+
+ if not name:
+ name = self.arguments[0]
+
+ lines = list(self.content)
+ mangle_docstrings(env.app, objtype, name, None, None, lines)
+ self.content = ViewList(lines, self.content.parent)
+
+ return base_directive.run(self)
+
+ return directive
+
diff --git a/doc/sphinxext/numpy_ext_old/__init__.py b/doc/sphinxext/numpy_ext_old/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/doc/sphinxext/numpy_ext_old/docscrape.py b/doc/sphinxext/numpy_ext_old/docscrape.py
new file mode 100644
index 0000000..a4b7c21
--- /dev/null
+++ b/doc/sphinxext/numpy_ext_old/docscrape.py
@@ -0,0 +1,492 @@
+"""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<role>\w+):`(?P<name>[a-zA-Z0-9_.-]+)`|"
+ r" (?P<name2>[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'):
+ self._f = func
+ self._role = role # e.g. "func" or "meth"
+ try:
+ NumpyDocString.__init__(self,inspect.getdoc(func) or '')
+ 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):
+ 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
+
+ NumpyDocString.__init__(self, pydoc.getdoc(cls))
+
+ @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/numpy_ext_old/docscrape_sphinx.py b/doc/sphinxext/numpy_ext_old/docscrape_sphinx.py
new file mode 100644
index 0000000..d431ecd
--- /dev/null
+++ b/doc/sphinxext/numpy_ext_old/docscrape_sphinx.py
@@ -0,0 +1,133 @@
+import re, inspect, textwrap, pydoc
+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 += ['']
+ 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):
+ 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)
+ elif what in ('function', 'method'):
+ return SphinxFunctionDoc(obj, '')
+ else:
+ return SphinxDocString(pydoc.getdoc(obj))
diff --git a/doc/sphinxext/numpydoc.py b/doc/sphinxext/numpy_ext_old/numpydoc.py
similarity index 88%
rename from doc/sphinxext/numpydoc.py
rename to doc/sphinxext/numpy_ext_old/numpydoc.py
index 89a8436..5e979ea 100644
--- a/doc/sphinxext/numpydoc.py
+++ b/doc/sphinxext/numpy_ext_old/numpydoc.py
@@ -1,5 +1,3 @@
-# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
-# vi: set ft=python sts=4 ts=4 sw=4 et:
"""
========
numpydoc
@@ -30,18 +28,13 @@ def mangle_docstrings(app, what, name, obj, options, lines,
re.I|re.S)
lines[:] = title_re.sub('', "\n".join(lines)).split("\n")
else:
- doc = get_doc_object(obj, what, "\n".join(lines))
+ doc = get_doc_object(obj, what)
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")]
+ v = dict(full_name=obj.__name__)
+ lines += [''] + (app.config.numpydoc_edit_link % v).split("\n")
# replace reference numbers so that there are no duplicates
references = []
@@ -90,7 +83,7 @@ def initialize(app):
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)
diff --git a/examples/README.txt b/examples/README.txt
new file mode 100644
index 0000000..aebe569
--- /dev/null
+++ b/examples/README.txt
@@ -0,0 +1,6 @@
+
+General examples
+-------------------
+
+General-purpose and introductory examples to MNE.
+
diff --git a/examples/compute_mne_inverse.py b/examples/compute_mne_inverse.py
index 1690acd..94efae0 100644
--- a/examples/compute_mne_inverse.py
+++ b/examples/compute_mne_inverse.py
@@ -1,4 +1,7 @@
-"""Compute MNE inverse solution
+"""
+============================
+Compute MNE inverse solution
+============================
"""
print __doc__
diff --git a/examples/read_bem_surfaces.py b/examples/read_bem_surfaces.py
index ae39890..127f9c4 100644
--- a/examples/read_bem_surfaces.py
+++ b/examples/read_bem_surfaces.py
@@ -1,4 +1,7 @@
-"""Reading BEM surfaces
+"""
+============================================
+Reading BEM surfaces from a forward solution
+============================================
"""
print __doc__
diff --git a/examples/read_cov.py b/examples/read_cov.py
index 142867a..9edffcd 100644
--- a/examples/read_cov.py
+++ b/examples/read_cov.py
@@ -1,4 +1,7 @@
-"""Reading/Writing a noise covariance matrix
+"""
+=========================================
+Reading/Writing a noise covariance matrix
+=========================================
"""
print __doc__
diff --git a/examples/read_epochs.py b/examples/read_epochs.py
index 4e47659..9be2862 100644
--- a/examples/read_epochs.py
+++ b/examples/read_epochs.py
@@ -1,4 +1,7 @@
-"""Example of reading epochs from a raw FIF file
+"""
+==================================
+Reading epochs from a raw FIF file
+==================================
"""
print __doc__
diff --git a/examples/read_events.py b/examples/read_events.py
index 0064295..3932161 100644
--- a/examples/read_events.py
+++ b/examples/read_events.py
@@ -1,4 +1,7 @@
-"""Reading an event file
+"""
+=====================
+Reading an event file
+=====================
"""
print __doc__
diff --git a/examples/read_evoked.py b/examples/read_evoked.py
index 0b5ad10..89bd0ff 100644
--- a/examples/read_evoked.py
+++ b/examples/read_evoked.py
@@ -1,4 +1,8 @@
-"""Reading and writing an evoked file
+"""
+==================================
+Reading and writing an evoked file
+==================================
+
"""
print __doc__
diff --git a/examples/read_forward.py b/examples/read_forward.py
index 725b3b3..75a9bad 100644
--- a/examples/read_forward.py
+++ b/examples/read_forward.py
@@ -1,4 +1,7 @@
-"""Reading a forward operator a.k.a. lead field matrix
+"""
+===================================================
+Reading a forward operator a.k.a. lead field matrix
+===================================================
"""
print __doc__
diff --git a/examples/read_inverse.py b/examples/read_inverse.py
index 7d6b359..96e8c47 100644
--- a/examples/read_inverse.py
+++ b/examples/read_inverse.py
@@ -1,4 +1,7 @@
-"""Reading an inverse operator
+"""
+===========================
+Reading an inverse operator
+===========================
"""
print __doc__
diff --git a/examples/read_raw.py b/examples/read_raw.py
index 8d41748..618084b 100644
--- a/examples/read_raw.py
+++ b/examples/read_raw.py
@@ -1,4 +1,7 @@
-"""Reading a raw file segment
+"""
+==========================
+Reading a raw file segment
+==========================
"""
print __doc__
diff --git a/examples/read_stc.py b/examples/read_stc.py
index d3032fd..17cd649 100644
--- a/examples/read_stc.py
+++ b/examples/read_stc.py
@@ -1,4 +1,7 @@
-"""Reading an STC file
+"""
+===================
+Reading an STC file
+===================
STC files contain activations on cortex ie. source
reconstructions
diff --git a/examples/read_write_raw.py b/examples/read_write_raw.py
index 3a38cb2..d340cf8 100644
--- a/examples/read_write_raw.py
+++ b/examples/read_write_raw.py
@@ -1,4 +1,7 @@
-"""Read and write raw data
+"""
+=======================
+Read and write raw data
+=======================
Read and write raw data in 60-sec blocks
"""
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/python-mne.git
More information about the debian-med-commit
mailing list