Skip to content

Commit

Permalink
MRG - merge from trunk
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthew Brett committed May 1, 2010
2 parents aea81df + 831fdf1 commit 74dee8c
Show file tree
Hide file tree
Showing 37 changed files with 1,364 additions and 48,982 deletions.
112 changes: 109 additions & 3 deletions build_docs.py → build_helpers.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
"""
Code to build the documentation in the setup.py
Build helpers for setup.py
To use this code, run::
Includes package dependency checks, and code to build the documentation
To build the docs, run::
python setup.py build_sphinx
"""

# Standard library imports
import sys
import os
from os.path import join as pjoin
from os.path import join as pjoin, dirname
import zipfile
import warnings
import shutil
from distutils.cmd import Command
from distutils.command.clean import clean
from distutils.version import LooseVersion
from distutils.dep_util import newer_group
from distutils.errors import DistutilsError

from numpy.distutils.misc_util import appendpath
from numpy.distutils import log

# Sphinx import.
from sphinx.setup_command import BuildDoc
Expand Down Expand Up @@ -167,3 +176,100 @@ def run(self):
}


# Dependency checks
def package_check(pkg_name, version=None,
optional=False,
checker=LooseVersion,
version_getter=None,
):
''' Check if package `pkg_name` is present, and correct version
Parameters
----------
pkg_name : str
name of package as imported into python
version : {None, str}, optional
minimum version of the package that we require. If None, we don't
check the version. Default is None
optional : {False, True}, optional
If False, raise error for absent package or wrong version;
otherwise warn
checker : callable, optional
callable with which to return comparable thing from version
string. Default is ``distutils.version.LooseVersion``
version_getter : {None, callable}:
Callable that takes `pkg_name` as argument, and returns the
package version string - as in::
``version = version_getter(pkg_name)``
If None, equivalent to::
mod = __import__(pkg_name); version = mod.__version__``
'''
if version_getter is None:
def version_getter(pkg_name):
mod = __import__(pkg_name)
return mod.__version__
try:
mod = __import__(pkg_name)
except ImportError:
if not optional:
raise RuntimeError('Cannot import package "%s" '
'- is it installed?' % pkg_name)
log.warn('Missing optional package "%s"; '
'you may get run-time errors' % pkg_name)
return
if not version:
return
try:
have_version = version_getter(pkg_name)
except AttributeError:
raise RuntimeError('Cannot find version for %s' % pkg_name)
if checker(have_version) < checker(version):
v_msg = 'You have version %s of package "%s"' \
' but we need version >= %s' % (
have_version,
pkg_name,
version,
)
if optional:
log.warn(v_msg + '; you may get run-time errors')
else:
raise RuntimeError(v_msg)


def generate_a_pyrex_source(self, base, ext_name, source, extension):
''' Monkey patch for numpy build_src.build_src method
Uses Cython instead of Pyrex.
Assumes Cython is present
'''
if self.inplace:
target_dir = dirname(base)
else:
target_dir = appendpath(self.build_src, dirname(base))
target_file = pjoin(target_dir, ext_name + '.c')
depends = [source] + extension.depends
# add distribution (package-wide) include directories, in order to
# pick up needed .pxd files for cython compilation
incl_dirs = extension.include_dirs[:]
dist_incl_dirs = self.distribution.include_dirs
if not dist_incl_dirs is None:
incl_dirs += dist_incl_dirs
if self.force or newer_group(depends, target_file, 'newer'):
import Cython.Compiler.Main
log.info("cythonc:> %s" % (target_file))
self.mkpath(target_dir)
options = Cython.Compiler.Main.CompilationOptions(
defaults=Cython.Compiler.Main.default_options,
include_path=incl_dirs,
output_file=target_file)
cython_result = Cython.Compiler.Main.compile(source,
options=options)
if cython_result.num_errors != 0:
raise DistutilsError("%d errors while compiling %r with Cython" \
% (cython_result.num_errors, source))
return target_file

32 changes: 23 additions & 9 deletions doc/sphinxext/autosummary.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@

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),
Expand Down Expand Up @@ -129,7 +136,8 @@ def autosummary_directive(dirname, arguments, options, content, lineno,
"""

names = []
names += [x.strip() for x in content if x.strip()]
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)
Expand Down Expand Up @@ -160,7 +168,7 @@ def autosummary_directive(dirname, arguments, options, content, lineno,
tocnode['includefiles'] = docnames
tocnode['maxdepth'] = -1
tocnode['glob'] = None
tocnode['entries'] = []
tocnode['entries'] = [(None, docname) for docname in docnames]

tocnode = autosummary_toc('', '', tocnode)
return warnings + [node] + [tocnode]
Expand Down Expand Up @@ -190,8 +198,8 @@ def get_autosummary(names, state, no_signatures=False):
table = nodes.table('')
group = nodes.tgroup('', cols=2)
table.append(group)
group.append(nodes.colspec('', colwidth=30))
group.append(nodes.colspec('', colwidth=70))
group.append(nodes.colspec('', colwidth=10))
group.append(nodes.colspec('', colwidth=90))
body = nodes.tbody('')
group.append(body)

Expand All @@ -202,6 +210,11 @@ def append_row(*column_texts):
vl = ViewList()
vl.append(text, '<autosummary>')
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)

Expand All @@ -223,20 +236,21 @@ def append_row(*column_texts):
else:
title = ""

col1 = ":obj:`%s <%s>`" % (name, real_name)
col1 = u":obj:`%s <%s>`" % (name, real_name)
if doc['Signature']:
sig = re.sub('^[a-zA-Z_0-9.-]*', '', 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)
sig = re.sub(r'(\[.{16,16}[^,]*?),.*?\]\)', r'\1, ...])', sig)
else:
sig = re.sub(r'(\(.{16,16}[^,)]*?),.*?\)', r'\1, ...)', sig)
col1 += " " + sig
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)

Expand Down
2 changes: 1 addition & 1 deletion doc/sphinxext/autosummary_generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def get_documented_in_lines(lines, module=None, filename=None):
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*')
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 = {}
Expand Down
46 changes: 24 additions & 22 deletions doc/sphinxext/docscrape.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import pydoc
from StringIO import StringIO
from warnings import warn
4

class Reader(object):
"""A line-based string reader.
Expand Down Expand Up @@ -84,7 +84,7 @@ def is_empty(self):


class NumpyDocString(object):
def __init__(self,docstring):
def __init__(self, docstring, config={}):
docstring = textwrap.dedent(docstring).split('\n')

self._doc = Reader(docstring)
Expand Down Expand Up @@ -183,7 +183,7 @@ def _parse_param_list(self,content):

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):
Expand Down Expand Up @@ -216,7 +216,7 @@ def push_item(name, rest):

current_func = None
rest = []

for line in content:
if not line.strip(): continue

Expand Down Expand Up @@ -258,7 +258,7 @@ def strip_each_in(lst):
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():
Expand All @@ -275,7 +275,7 @@ def _parse_summary(self):

if not self._is_at_section():
self['Extended Summary'] = self._read_to_next_section()

def _parse(self):
self._doc.reset()
self._parse_summary()
Expand Down Expand Up @@ -386,6 +386,8 @@ def __str__(self, func_role=''):
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)

Expand All @@ -406,7 +408,7 @@ def header(text, style='-'):


class FunctionDoc(NumpyDocString):
def __init__(self, func, role='func', doc=None):
def __init__(self, func, role='func', doc=None, config={}):
self._f = func
self._role = role # e.g. "func" or "meth"
if doc is None:
Expand Down Expand Up @@ -440,7 +442,7 @@ def get_func(self):
else:
func = self._f
return func, func_name

def __str__(self):
out = ''

Expand All @@ -461,7 +463,8 @@ def __str__(self):


class ClassDoc(NumpyDocString):
def __init__(self,cls,modulename='',func_doc=FunctionDoc,doc=None):
def __init__(self, cls, doc=None, modulename='', func_doc=FunctionDoc,
config={}):
if not inspect.isclass(cls):
raise ValueError("Initialise using a class. Got %r" % cls)
self._cls = cls
Expand All @@ -477,21 +480,20 @@ def __init__(self,cls,modulename='',func_doc=FunctionDoc,doc=None):

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):
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


@property
def properties(self):
return [name for name,func in inspect.getmembers(self._cls)
if not name.startswith('_') and func is None]
Loading

0 comments on commit 74dee8c

Please sign in to comment.