[svn r37540] Nicer formatting of docstrings (de-indented and such), fixed problem getting
to frame source (IOError that popped up when building the py lib's api docs) in description.py. --HG-- branch : trunk
This commit is contained in:
parent
02abf0ee5d
commit
06cbe63616
|
@ -12,6 +12,41 @@ sorted = py.builtin.sorted
|
||||||
html = py.xml.html
|
html = py.xml.html
|
||||||
raw = py.xml.raw
|
raw = py.xml.raw
|
||||||
|
|
||||||
|
def deindent(str, linesep=os.linesep):
|
||||||
|
""" de-indent string
|
||||||
|
|
||||||
|
can be used to de-indent Python docstrings, it de-indents the first
|
||||||
|
line to the side always, and determines the indentation of the rest
|
||||||
|
of the text by taking that of the least indented (filled) line
|
||||||
|
"""
|
||||||
|
lines = str.split(linesep)
|
||||||
|
normalized = []
|
||||||
|
deindent = None
|
||||||
|
normalized.append(lines[0].strip())
|
||||||
|
for line in lines[1:]:
|
||||||
|
if not line.strip():
|
||||||
|
normalized.append('')
|
||||||
|
else:
|
||||||
|
line = line.rstrip()
|
||||||
|
line = line.replace('\t', ' ')
|
||||||
|
indent = 0
|
||||||
|
for c in line:
|
||||||
|
if c != ' ':
|
||||||
|
break
|
||||||
|
indent += 1
|
||||||
|
if deindent is None or indent < deindent:
|
||||||
|
deindent = indent
|
||||||
|
normalized.append(line)
|
||||||
|
while normalized[-1] == '':
|
||||||
|
normalized.pop()
|
||||||
|
ret = [normalized[0]]
|
||||||
|
for line in normalized[1:]:
|
||||||
|
if not line:
|
||||||
|
ret.append(line)
|
||||||
|
else:
|
||||||
|
ret.append(line[deindent:])
|
||||||
|
return '%s\n' % (linesep.join(ret),)
|
||||||
|
|
||||||
# HTML related stuff
|
# HTML related stuff
|
||||||
class H(html):
|
class H(html):
|
||||||
class Content(html.div):
|
class Content(html.div):
|
||||||
|
@ -50,8 +85,9 @@ class H(html):
|
||||||
class ParameterDescription(html.div):
|
class ParameterDescription(html.div):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class Docstring(html.div):
|
class Docstring(html.pre):
|
||||||
style = html.Style(white_space='pre', min_height='3em')
|
#style = html.Style(white_space='pre', min_height='3em')
|
||||||
|
pass
|
||||||
|
|
||||||
class Navigation(html.div):
|
class Navigation(html.div):
|
||||||
style = html.Style(min_height='99%', float='left', margin_top='1.2em',
|
style = html.Style(min_height='99%', float='left', margin_top='1.2em',
|
||||||
|
@ -310,6 +346,8 @@ class ApiPageBuilder(AbstractPageBuilder):
|
||||||
# XXX we may want to have seperate
|
# XXX we may want to have seperate
|
||||||
func = self.dsa.get_obj(dotted_name)
|
func = self.dsa.get_obj(dotted_name)
|
||||||
docstring = func.__doc__
|
docstring = func.__doc__
|
||||||
|
if docstring:
|
||||||
|
docstring = deindent(docstring)
|
||||||
localname = func.__name__
|
localname = func.__name__
|
||||||
argdesc = get_param_htmldesc(self.linker, func)
|
argdesc = get_param_htmldesc(self.linker, func)
|
||||||
valuedesc = self.build_callable_signature_description(dotted_name)
|
valuedesc = self.build_callable_signature_description(dotted_name)
|
||||||
|
@ -343,7 +381,7 @@ class ApiPageBuilder(AbstractPageBuilder):
|
||||||
)
|
)
|
||||||
snippet = H.FunctionDescription(
|
snippet = H.FunctionDescription(
|
||||||
H.FunctionDef(localname, argdesc),
|
H.FunctionDef(localname, argdesc),
|
||||||
H.Docstring(docstring or H.em('no docstring available')),
|
H.Docstring(docstring or '*no docstring available*'),
|
||||||
H.div(H.a('show/hide info',
|
H.div(H.a('show/hide info',
|
||||||
href='#',
|
href='#',
|
||||||
onclick=('showhideel(getnextsibling(this));'
|
onclick=('showhideel(getnextsibling(this));'
|
||||||
|
@ -372,6 +410,8 @@ class ApiPageBuilder(AbstractPageBuilder):
|
||||||
href=self.linker.get_lazyhref(sourcefile)))
|
href=self.linker.get_lazyhref(sourcefile)))
|
||||||
|
|
||||||
docstring = cls.__doc__
|
docstring = cls.__doc__
|
||||||
|
if docstring:
|
||||||
|
docstring = deindent(docstring)
|
||||||
methods = self.dsa.get_class_methods(dotted_name)
|
methods = self.dsa.get_class_methods(dotted_name)
|
||||||
basehtml = []
|
basehtml = []
|
||||||
bases = self.dsa.get_possible_base_classes(dotted_name)
|
bases = self.dsa.get_possible_base_classes(dotted_name)
|
||||||
|
@ -394,7 +434,7 @@ class ApiPageBuilder(AbstractPageBuilder):
|
||||||
snippet = H.ClassDescription(
|
snippet = H.ClassDescription(
|
||||||
# XXX bases HTML
|
# XXX bases HTML
|
||||||
H.ClassDef('%s(' % (clsname,), *basehtml),
|
H.ClassDef('%s(' % (clsname,), *basehtml),
|
||||||
H.Docstring(docstring or H.em('no docstring available')),
|
H.Docstring(docstring or '*no docstring available*'),
|
||||||
sourcelink,
|
sourcelink,
|
||||||
)
|
)
|
||||||
if methods:
|
if methods:
|
||||||
|
@ -413,9 +453,11 @@ class ApiPageBuilder(AbstractPageBuilder):
|
||||||
docstring = None
|
docstring = None
|
||||||
else:
|
else:
|
||||||
docstring = obj.__doc__
|
docstring = obj.__doc__
|
||||||
|
if docstring:
|
||||||
|
docstring = deindent(docstring)
|
||||||
snippet = H.NamespaceDescription(
|
snippet = H.NamespaceDescription(
|
||||||
H.NamespaceDef(namespace_dotted_name),
|
H.NamespaceDef(namespace_dotted_name),
|
||||||
H.Docstring(docstring or H.em('no docstring available'))
|
H.Docstring(docstring or '*no docstring available*')
|
||||||
)
|
)
|
||||||
for dotted_name in sorted(item_dotted_names):
|
for dotted_name in sorted(item_dotted_names):
|
||||||
itemname = dotted_name.split('.')[-1]
|
itemname = dotted_name.split('.')[-1]
|
||||||
|
|
|
@ -69,6 +69,13 @@ def setup_fs_project(name):
|
||||||
assert pak.main.sub.func(20) is None
|
assert pak.main.sub.func(20) is None
|
||||||
s = pak.main.func(pak.main.SomeTestClass, 10)
|
s = pak.main.func(pak.main.SomeTestClass, 10)
|
||||||
assert isinstance(s, pak.main.SomeTestClass)
|
assert isinstance(s, pak.main.SomeTestClass)
|
||||||
|
|
||||||
|
# some nice things to confuse the tracer/storage
|
||||||
|
source = py.code.Source('''\
|
||||||
|
pak.main.sub.func(10)
|
||||||
|
''')
|
||||||
|
c = compile(str(source), '<test>', 'exec')
|
||||||
|
exec c in globals()
|
||||||
"""))
|
"""))
|
||||||
return temp, 'pak'
|
return temp, 'pak'
|
||||||
|
|
||||||
|
|
|
@ -43,3 +43,12 @@ def test_source_dirs_files():
|
||||||
assert dirnames == ['sub']
|
assert dirnames == ['sub']
|
||||||
assert filenames == ['file1.py', 'file3.c']
|
assert filenames == ['file1.py', 'file3.c']
|
||||||
|
|
||||||
|
def test_deindent():
|
||||||
|
assert htmlgen.deindent('foo\n\n bar\n ') == 'foo\n\nbar\n'
|
||||||
|
assert htmlgen.deindent(' foo\n\n bar\n ') == 'foo\n\nbar\n'
|
||||||
|
assert htmlgen.deindent('foo\n\n bar\n baz') == 'foo\n\nbar\nbaz\n'
|
||||||
|
assert htmlgen.deindent(' foo\n\n bar\n baz\n') == (
|
||||||
|
'foo\n\nbar\n baz\n')
|
||||||
|
assert htmlgen.deindent('foo\n\n bar\n baz\n') == (
|
||||||
|
'foo\n\n bar\nbaz\n')
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,10 @@ class CallFrame(object):
|
||||||
self.filename = frame.code.raw.co_filename
|
self.filename = frame.code.raw.co_filename
|
||||||
self.lineno = frame.lineno
|
self.lineno = frame.lineno
|
||||||
self.firstlineno = frame.code.firstlineno
|
self.firstlineno = frame.code.firstlineno
|
||||||
|
try:
|
||||||
self.source = getsource(frame.code.raw)
|
self.source = getsource(frame.code.raw)
|
||||||
|
except IOError:
|
||||||
|
self.source = "could not get to source"
|
||||||
|
|
||||||
def _getval(self):
|
def _getval(self):
|
||||||
return (self.filename, self.lineno)
|
return (self.filename, self.lineno)
|
||||||
|
|
Loading…
Reference in New Issue