Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 37 additions & 28 deletions numpydoc/docscrape.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,18 @@ def __init__(self, data):
String with lines separated by '\n'.

"""
if isinstance(data,list):
if isinstance(data, list):
self._str = data
else:
self._str = data.split('\n') # store string as list of lines
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
self._l = 0 # current line nr

def read(self):
if not self.eof():
Expand Down Expand Up @@ -67,16 +67,18 @@ def read_to_condition(self, condition_func):

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):
def peek(self, n=0):
if self._l + n < len(self._str):
return self[self._l + n]
else:
Expand Down Expand Up @@ -139,25 +141,27 @@ def _is_at_section(self):
if l1.startswith('.. index::'):
return True

l2 = self._doc.peek(1).strip() # ---------- or ==========
l2 = self._doc.peek(1).strip() # ---------- or ==========
return l2.startswith('-'*len(l1)) or l2.startswith('='*len(l1))

def _strip(self,doc):
def _strip(self, doc):
i = 0
j = 0
for i,line in enumerate(doc):
if line.strip(): break
for i, line in enumerate(doc):
if line.strip():
break

for j,line in enumerate(doc[::-1]):
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
if not self._doc.peek(-1).strip(): # previous line was empty
section += ['']

section += self._doc.read_to_next_empty_line()
Expand All @@ -169,14 +173,14 @@ def _read_sections(self):
data = self._read_to_next_section()
name = data[0].strip()

if name.startswith('..'): # index section
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):
def _parse_param_list(self, content):
r = Reader(content)
params = []
while not r.eof():
Expand All @@ -189,13 +193,13 @@ def _parse_param_list(self,content):
desc = r.read_to_next_unindented_line()
desc = dedent_lines(desc)

params.append((arg_name,arg_type,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
Expand Down Expand Up @@ -228,7 +232,8 @@ def push_item(name, rest):
rest = []

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

m = self._name_rgx.match(line)
if m and line[m.end():].strip().startswith(':'):
Expand Down Expand Up @@ -307,7 +312,8 @@ def _parse(self):

for (section, content) in sections:
if not section.startswith('..'):
section = ' '.join([s.capitalize() for s in section.split(' ')])
section = (s.capitalize() for s in section.split(' '))
section = ' '.join(section)
if section in ('Parameters', 'Returns', 'Yields', 'Raises',
'Warns', 'Other Parameters', 'Attributes',
'Methods'):
Expand All @@ -332,7 +338,7 @@ def _str_indent(self, doc, indent=4):

def _str_signature(self):
if self['Signature']:
return [self['Signature'].replace('*','\*')] + ['']
return [self['Signature'].replace('*', '\*')] + ['']
else:
return ['']

Expand All @@ -352,7 +358,7 @@ def _str_param_list(self, name):
out = []
if self[name]:
out += self._str_header(name)
for param,param_type,desc in self[name]:
for param, param_type, desc in self[name]:
if param_type:
out += ['%s : %s' % (param, param_type)]
else:
Expand All @@ -370,7 +376,8 @@ def _str_section(self, name):
return out

def _str_see_also(self, func_role):
if not self['See Also']: return []
if not self['See Also']:
return []
out = []
out += self._str_header("See Also")
last_had_desc = True
Expand All @@ -397,7 +404,7 @@ def _str_see_also(self, func_role):
def _str_index(self):
idx = self['index']
out = []
out += ['.. index:: %s' % idx.get('default','')]
out += ['.. index:: %s' % idx.get('default', '')]
for section, references in idx.items():
if section == 'default':
continue
Expand All @@ -414,33 +421,35 @@ def __str__(self, func_role=''):
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'):
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):
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"
self._role = role # e.g. "func" or "meth"

if doc is None:
if func is None:
Expand All @@ -457,7 +466,7 @@ def __init__(self, func, role='func', doc=None, config={}):
else:
argspec = inspect.getargspec(func)
argspec = inspect.formatargspec(*argspec)
argspec = argspec.replace('*','\*')
argspec = argspec.replace('*', '\*')
signature = '%s%s' % (func_name, argspec)
except TypeError as e:
signature = '%s()' % func_name
Expand All @@ -483,7 +492,7 @@ def __str__(self):
if self._role:
if self._role not in roles:
print("Warning: invalid role %s" % self._role)
out += '.. %s:: %s\n \n\n' % (roles.get(self._role,''),
out += '.. %s:: %s\n \n\n' % (roles.get(self._role, ''),
func_name)

out += super(FunctionDoc, self).__str__(func_role=self._role)
Expand All @@ -500,8 +509,8 @@ def __init__(self, cls, doc=None, modulename='', func_doc=FunctionDoc,
raise ValueError("Expected a class or None, but got %r" % cls)
self._cls = cls

self.show_inherited_members = config.get('show_inherited_class_members',
True)
self.show_inherited_members = config.get(
'show_inherited_class_members', True)

if modulename and not modulename.endswith('.'):
modulename += '.'
Expand Down
19 changes: 14 additions & 5 deletions numpydoc/docscrape_sphinx.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
from __future__ import division, absolute_import, print_function

import sys, re, inspect, textwrap, pydoc
import sys
import re
import inspect
import textwrap
import pydoc
import sphinx
import collections

from .docscrape import NumpyDocString, FunctionDoc, ClassDoc

if sys.version_info[0] >= 3:
Expand Down Expand Up @@ -171,7 +176,7 @@ def _str_index(self):
if len(idx) == 0:
return out

out += ['.. index:: %s' % idx.get('default','')]
out += ['.. index:: %s' % idx.get('default', '')]
for section, references in idx.items():
if section == 'default':
continue
Expand All @@ -192,9 +197,9 @@ def _str_references(self):
# Latex collects all references to a separate bibliography,
# so we need to insert links to it
if sphinx.__version__ >= "0.6":
out += ['.. only:: latex','']
out += ['.. only:: latex', '']
else:
out += ['.. latexonly::','']
out += ['.. latexonly::', '']
items = []
for line in self['References']:
m = re.match(r'.. \[([a-z0-9._-]+)\]', line, re.I)
Expand Down Expand Up @@ -235,25 +240,29 @@ def __str__(self, indent=0, func_role="obj"):
out += self._str_examples()
for param_list in ('Attributes', 'Methods'):
out += self._str_member_list(param_list)
out = self._str_indent(out,indent)
out = self._str_indent(out, indent)
return '\n'.join(out)


class SphinxFunctionDoc(SphinxDocString, FunctionDoc):
def __init__(self, obj, doc=None, config={}):
self.load_config(config)
FunctionDoc.__init__(self, obj, doc=doc, config=config)


class SphinxClassDoc(SphinxDocString, ClassDoc):
def __init__(self, obj, doc=None, func_doc=None, config={}):
self.load_config(config)
ClassDoc.__init__(self, obj, doc=doc, func_doc=None, config=config)


class SphinxObjDoc(SphinxDocString):
def __init__(self, obj, doc=None, config={}):
self._f = obj
self.load_config(config)
SphinxDocString.__init__(self, doc, config=config)


def get_doc_object(obj, what=None, doc=None, config={}):
if what is None:
if inspect.isclass(obj):
Expand Down
Loading