1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
"""
===========
scipyoptdoc
===========
Proper docstrings for scipy.optimize.minimize et al.
Usage::
.. scipy-optimize:function:: scipy.optimize.minimize
:impl: scipy.optimize.optimize._minimize_nelder_mead
:method: Nelder-Mead
Produces output similar to autodoc, except
- The docstring is obtained from the 'impl' function
- The call signature is mangled so that the default values for method keyword
and options dict are substituted
- 'Parameters' section is replaced by 'Options' section
- See Also link to the actual function documentation is inserted
"""
from __future__ import division, absolute_import, print_function
import os, sys, re, pydoc
import sphinx
import inspect
import collections
import textwrap
if sphinx.__version__ < '1.0.1':
raise RuntimeError("Sphinx 1.0.1 or newer is required")
from numpydoc.numpydoc import mangle_docstrings
from docutils.parsers.rst import Directive
from docutils.statemachine import ViewList
from sphinx.domains.python import PythonDomain
if sys.version_info[0] >= 3:
sixu = lambda s: s
else:
sixu = lambda s: unicode(s, 'unicode_escape')
def setup(app):
app.add_domain(ScipyOptimizeInterfaceDomain)
def _option_required_str(x):
if not x:
raise ValueError("value is required")
return str(x)
def _import_object(name):
parts = name.split('.')
module_name = '.'.join(parts[:-1])
__import__(module_name)
obj = getattr(sys.modules[module_name], parts[-1])
return obj
class ScipyOptimizeInterfaceDomain(PythonDomain):
name = 'scipy-optimize'
def __init__(self, *a, **kw):
super(ScipyOptimizeInterfaceDomain, self).__init__(*a, **kw)
self.directives = dict(self.directives)
self.directives['function'] = wrap_mangling_directive(self.directives['function'])
BLURB = """
.. seealso:: For documentation for the rest of the parameters, see `%s`
"""
def wrap_mangling_directive(base_directive):
class directive(base_directive):
def run(self):
env = self.state.document.settings.env
# Interface function
name = self.arguments[0].strip()
obj = _import_object(name)
args, varargs, keywords, defaults = inspect.getargspec(obj)
# Implementation function
impl_name = self.options['impl']
impl_obj = _import_object(impl_name)
impl_args, impl_varargs, impl_keywords, impl_defaults = inspect.getargspec(impl_obj)
# Format signature taking implementation into account
args = list(args)
defaults = list(defaults)
def set_default(arg, value):
j = args.index(arg)
defaults[len(defaults) - (len(args) - j)] = value
def remove_arg(arg):
if arg not in args:
return
j = args.index(arg)
if j < len(args) - len(defaults):
del args[j]
else:
del defaults[len(defaults) - (len(args) - j)]
del args[j]
options = []
for j, opt_name in enumerate(impl_args):
if opt_name in args:
continue
if j >= len(impl_args) - len(impl_defaults):
options.append((opt_name, impl_defaults[len(impl_defaults) - (len(impl_args) - j)]))
else:
options.append((opt_name, None))
set_default('options', dict(options))
set_default('method', self.options['method'].strip())
for arg in list(args):
if arg not in impl_args and arg not in ('fun', 'x0', 'args', 'tol',
'callback', 'method', 'options'):
remove_arg(arg)
signature = inspect.formatargspec(args, varargs, keywords, defaults)
# Produce output
self.options['noindex'] = True
self.arguments[0] = name + signature
lines = textwrap.dedent(pydoc.getdoc(impl_obj)).splitlines()
new_lines = []
for line in lines:
if line.strip() == 'Options':
new_lines.append("Other Parameters")
elif line.strip() == "-"*len('Options'):
new_lines.append("-"*len("Other Parameters"))
else:
new_lines.append(line)
mangle_docstrings(env.app, 'function', name, None, None, new_lines)
lines = new_lines
new_lines = []
for line in lines:
if line.strip() == ':Other Parameters:':
new_lines.extend((BLURB % (name,)).splitlines())
new_lines.append(':Options:')
else:
new_lines.append(line)
self.content = ViewList(new_lines, self.content.parent)
return base_directive.run(self)
option_spec = dict(base_directive.option_spec)
option_spec['impl'] = _option_required_str
option_spec['method'] = _option_required_str
return directive
|