mirror of
https://github.com/wxWidgets/Phoenix.git
synced 2025-12-16 09:40:07 +01:00
Phoenix:
- First stub at integrating `wx.lib` (116 warnings); - Added `internationalization.rst` file from Werner (with a cool sample app as well); - Added new samples for AffineMatrix2D. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxPython/Phoenix/trunk@71099 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -144,8 +144,68 @@ HTML_REPLACE = ['module', 'function', 'method', 'class', 'classmethod', 'staticm
|
||||
|
||||
# The SVN revision of wxWidgets/Phoenix used to build the Sphinx docs.
|
||||
# There must be a more intelligent way to get this information automatically.
|
||||
SVN_REVISION = '71086'
|
||||
SVN_REVISION = '71066'
|
||||
|
||||
# Today's date representation for the Sphinx HTML docs
|
||||
TODAY = datetime.date.today().strftime('%d %B %Y')
|
||||
|
||||
# wx.lib and other pure-Python stuff
|
||||
|
||||
class Enumeration(object):
|
||||
|
||||
def __init__(self, name, enumList):
|
||||
|
||||
self.__doc__ = name
|
||||
lookup = { }
|
||||
reverseLookup = { }
|
||||
i = 0
|
||||
uniqueNames = [ ]
|
||||
uniqueValues = [ ]
|
||||
|
||||
for item in enumList:
|
||||
x = item.upper()
|
||||
uniqueNames.append(x)
|
||||
uniqueValues.append(i)
|
||||
lookup[x] = i
|
||||
reverseLookup[i] = x
|
||||
i = i + 1
|
||||
|
||||
self.lookup = lookup
|
||||
self.reverseLookup = reverseLookup
|
||||
|
||||
def __getattr__(self, attr):
|
||||
|
||||
if not self.lookup.has_key(attr):
|
||||
raise AttributeError
|
||||
|
||||
return self.lookup[attr]
|
||||
|
||||
def whatis(self, value):
|
||||
|
||||
return self.reverseLookup[value]
|
||||
|
||||
|
||||
CONSTANT_RE = re.compile('^([\w\s,]+)=', re.M)
|
||||
|
||||
EXCLUDED_ATTRS = ['__builtins__', '__doc__', '__name__', '__file__', '__path__',
|
||||
'__module__', '__all__']
|
||||
|
||||
TYPE_DESCRIPTION = ['library',
|
||||
'package',
|
||||
'py_module', 'pyd_module', 'pyc_module', 'pyw_module',
|
||||
'klass',
|
||||
'function',
|
||||
'method', 'static_method', 'class_method', 'instance_method',
|
||||
'method_descriptor', 'builtin_method', 'builtin_function',
|
||||
'property',
|
||||
'booltype', 'classtype', 'complextype', 'dictproxytype', 'dicttype', 'filetype',
|
||||
'floattype', 'instancetype', 'inttype', 'lambdatype', 'listtype', 'longtype',
|
||||
'nonetype', 'objecttype', 'slicetype', 'strtype', 'tracebacktype', 'tupletype',
|
||||
'typetype', 'unicodetype', 'unknowntype', 'xrangetype']
|
||||
|
||||
object_types = Enumeration('Object_Types', TYPE_DESCRIPTION)
|
||||
|
||||
MODULE_TO_ICON = [(".py", object_types.PY_MODULE, "Py_Module"), (".pyd", object_types.PYD_MODULE, "Pyd_Module"),
|
||||
(".pyc", object_types.PYC_MODULE, "Pyc_Module"), (".pyw", object_types.PYW_MODULE, "Pyw_Module"),
|
||||
(".so", object_types.PYD_MODULE, "Pyd_Module")]
|
||||
|
||||
|
||||
@@ -25,192 +25,246 @@ ENOENT = getattr(errno, 'ENOENT', 0)
|
||||
EPIPE = getattr(errno, 'EPIPE', 0)
|
||||
|
||||
|
||||
class InheritanceDiagram(object):
|
||||
"""
|
||||
Given a list of classes, determines the set of classes that they inherit
|
||||
from all the way to the root "object", and then is able to generate a
|
||||
graphviz dot graph from them.
|
||||
"""
|
||||
|
||||
# ----------------------------------------------------------------------- #
|
||||
|
||||
def __init__(self, class_info):
|
||||
|
||||
#print class_info
|
||||
#print
|
||||
#print
|
||||
|
||||
self.class_info, self.specials = class_info
|
||||
|
||||
|
||||
# These are the default attrs for graphviz
|
||||
default_graph_attrs = {
|
||||
'rankdir': 'LR',
|
||||
'size': '"8.0, 12.0"',
|
||||
}
|
||||
default_node_attrs = {
|
||||
'shape': 'box',
|
||||
'fontsize': 10,
|
||||
'height': 0.3,
|
||||
'fontname': 'Vera Sans, DejaVu Sans, Liberation Sans, '
|
||||
'Arial, Helvetica, sans',
|
||||
'style': '"setlinewidth(0.5)"',
|
||||
}
|
||||
default_edge_attrs = {
|
||||
'arrowsize': 0.5,
|
||||
'style': '"setlinewidth(0.5)"',
|
||||
}
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------- #
|
||||
|
||||
def FormatNodeAttrs(self, attrs):
|
||||
|
||||
return ','.join(['%s=%s' % x for x in attrs.items()])
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------- #
|
||||
|
||||
def FormatGraphAttrs(self, attrs):
|
||||
|
||||
return ''.join(['%s=%s;\n' % x for x in attrs.items()])
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------- #
|
||||
|
||||
def GenerateDot(self, name="dummy"):
|
||||
"""
|
||||
Generate a graphviz dot graph from the classes that were passed in to `__init__`.
|
||||
|
||||
:param string `name`: the name of the graph.
|
||||
|
||||
:rtype: `string`
|
||||
|
||||
:returns: A string representing the Graphviz dot diagram.
|
||||
"""
|
||||
|
||||
inheritance_graph_attrs = dict(fontsize=9, ratio='auto', size='""', rankdir="LR")
|
||||
inheritance_node_attrs = {"align": "center", 'shape': 'box',
|
||||
'fontsize': 10, 'height': 0.3,
|
||||
'fontname': 'Vera Sans, DejaVu Sans, Liberation Sans, '
|
||||
'Arial, Helvetica, sans', 'style': '"setlinewidth(0.5)"',
|
||||
'labelloc': 'c', 'fontcolor': 'grey45'}
|
||||
|
||||
inheritance_edge_attrs = {'arrowsize': 0.5, 'style': '"setlinewidth(0.5)"', "color": "black"}
|
||||
|
||||
g_attrs = self.default_graph_attrs.copy()
|
||||
n_attrs = self.default_node_attrs.copy()
|
||||
e_attrs = self.default_edge_attrs.copy()
|
||||
g_attrs.update(inheritance_graph_attrs)
|
||||
n_attrs.update(inheritance_node_attrs)
|
||||
e_attrs.update(inheritance_edge_attrs)
|
||||
|
||||
res = []
|
||||
res.append('digraph %s {\n' % name)
|
||||
res.append(self.FormatGraphAttrs(g_attrs))
|
||||
|
||||
for name, fullname, bases in self.class_info.values():
|
||||
# Write the node
|
||||
this_node_attrs = n_attrs.copy()
|
||||
|
||||
if name in self.specials:
|
||||
this_node_attrs['fontcolor'] = 'black'
|
||||
this_node_attrs['color'] = 'blue'
|
||||
this_node_attrs['style'] = 'bold'
|
||||
|
||||
newname, fullname = Wx2Sphinx(name)
|
||||
|
||||
this_node_attrs['URL'] = '"%s.html"'%fullname
|
||||
res.append(' "%s" [%s];\n' %
|
||||
(newname, self.FormatNodeAttrs(this_node_attrs)))
|
||||
|
||||
# Write the edges
|
||||
for base_name in bases:
|
||||
|
||||
this_edge_attrs = e_attrs.copy()
|
||||
if name in self.specials:
|
||||
this_edge_attrs['color'] = 'red'
|
||||
|
||||
base_name, dummy = Wx2Sphinx(base_name)
|
||||
|
||||
res.append(' "%s" -> "%s" [%s];\n' %
|
||||
(base_name, newname,
|
||||
self.FormatNodeAttrs(this_edge_attrs)))
|
||||
res.append('}\n')
|
||||
return ''.join(res)
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------- #
|
||||
|
||||
def MakeInheritanceDiagram(self):
|
||||
"""
|
||||
Actually generates the inheritance diagram as a PNG file plus the corresponding
|
||||
MAP file for mouse navigation over the inheritance boxes.
|
||||
|
||||
These two files are saved into the ``INHERITANCEROOT`` folder (see `sphinxtools/constants.py`
|
||||
for more information).
|
||||
|
||||
:rtype: `tuple`
|
||||
|
||||
:returns: a tuple containing the PNG file name and a string representing the content
|
||||
of the MAP file (with newlines stripped away).
|
||||
|
||||
.. note:: The MAP file is deleted as soon as its content has been read.
|
||||
"""
|
||||
|
||||
code = self.GenerateDot()
|
||||
|
||||
# graphviz expects UTF-8 by default
|
||||
if isinstance(code, unicode):
|
||||
code = code.encode('utf-8')
|
||||
|
||||
static_root = INHERITANCEROOT
|
||||
|
||||
dot_args = ['dot']
|
||||
dummy, filename = Wx2Sphinx(self.specials[0])
|
||||
outfn = os.path.join(static_root, filename + '_inheritance.png')
|
||||
|
||||
if os.path.isfile(outfn):
|
||||
os.remove(outfn)
|
||||
if os.path.isfile(outfn + '.map'):
|
||||
os.remove(outfn + '.map')
|
||||
|
||||
dot_args.extend(['-Tpng', '-o' + outfn])
|
||||
dot_args.extend(['-Tcmapx', '-o%s.map' % outfn])
|
||||
|
||||
try:
|
||||
|
||||
p = Popen(dot_args, stdout=PIPE, stdin=PIPE, stderr=PIPE)
|
||||
|
||||
except OSError, err:
|
||||
|
||||
if err.errno != ENOENT: # No such file or directory
|
||||
raise
|
||||
|
||||
print '\nERROR: Graphviz command `dot` cannot be run (needed for Graphviz output), check your ``PATH`` setting'
|
||||
|
||||
try:
|
||||
# Graphviz may close standard input when an error occurs,
|
||||
# resulting in a broken pipe on communicate()
|
||||
stdout, stderr = p.communicate(code)
|
||||
|
||||
except OSError, err:
|
||||
|
||||
# in this case, read the standard output and standard error streams
|
||||
# directly, to get the error message(s)
|
||||
stdout, stderr = p.stdout.read(), p.stderr.read()
|
||||
p.wait()
|
||||
|
||||
if p.returncode != 0:
|
||||
print '\nERROR: Graphviz `dot` command exited with error:\n[stderr]\n%s\n[stdout]\n%s\n\n' % (stderr, stdout)
|
||||
|
||||
mapfile = outfn + '.map'
|
||||
|
||||
fid = open(mapfile, 'rt')
|
||||
map = fid.read()
|
||||
fid.close()
|
||||
|
||||
os.remove(mapfile)
|
||||
|
||||
return os.path.split(outfn)[1], map.replace('\n', ' ')
|
||||
|
||||
class InheritanceDiagram(object):
|
||||
"""
|
||||
Given a list of classes, determines the set of classes that they inherit
|
||||
from all the way to the root "object", and then is able to generate a
|
||||
graphviz dot graph from them.
|
||||
"""
|
||||
|
||||
def __init__(self, classes, main_class=None):
|
||||
|
||||
if main_class is None:
|
||||
self.class_info, self.specials = classes
|
||||
self.class_info = self.class_info.values()
|
||||
else:
|
||||
self.class_info, self.specials = self._class_info(classes)
|
||||
|
||||
self.main_class = main_class
|
||||
|
||||
|
||||
def _class_info(self, classes):
|
||||
"""Return name and bases for all classes that are ancestors of
|
||||
*classes*.
|
||||
|
||||
*parts* gives the number of dotted name parts that is removed from the
|
||||
displayed node names.
|
||||
"""
|
||||
|
||||
all_classes = {}
|
||||
specials = []
|
||||
|
||||
def recurse(cls):
|
||||
nodename, fullname = self.class_name(cls)
|
||||
|
||||
baselist = []
|
||||
all_classes[cls] = (nodename, fullname, baselist)
|
||||
|
||||
for base in cls.__bases__:
|
||||
baselist.append(self.class_name(base)[0])
|
||||
if base not in all_classes:
|
||||
recurse(base)
|
||||
|
||||
for cls in classes:
|
||||
recurse(cls)
|
||||
specials.append(self.class_name(cls)[1])
|
||||
|
||||
return all_classes.values(), specials
|
||||
|
||||
|
||||
def class_name(self, cls):
|
||||
"""Given a class object, return a fully-qualified name.
|
||||
|
||||
This works for things I've tested in matplotlib so far, but may not be
|
||||
completely general.
|
||||
"""
|
||||
|
||||
module = cls.__module__
|
||||
|
||||
if module == '__builtin__':
|
||||
fullname = cls.__name__
|
||||
else:
|
||||
fullname = '%s.%s' % (module, cls.__name__)
|
||||
|
||||
name_parts = fullname.split('.')
|
||||
if 'wx._' in fullname:
|
||||
nodename = fullname = name_parts[-1]
|
||||
else:
|
||||
# Just the last 2 parts
|
||||
nodename = '.'.join(name_parts[-2:])
|
||||
|
||||
return nodename, fullname
|
||||
|
||||
|
||||
# These are the default attrs for graphviz
|
||||
default_graph_attrs = {
|
||||
'rankdir': 'LR',
|
||||
'size': '"8.0, 12.0"',
|
||||
}
|
||||
default_node_attrs = {
|
||||
'shape': 'box',
|
||||
'fontsize': 10,
|
||||
'height': 0.3,
|
||||
'fontname': 'Vera Sans, DejaVu Sans, Liberation Sans, '
|
||||
'Arial, Helvetica, sans',
|
||||
'style': '"setlinewidth(0.5)"',
|
||||
}
|
||||
default_edge_attrs = {
|
||||
'arrowsize': 0.5,
|
||||
'style': '"setlinewidth(0.5)"',
|
||||
}
|
||||
|
||||
def _format_node_attrs(self, attrs):
|
||||
return ','.join(['%s=%s' % x for x in attrs.items()])
|
||||
|
||||
def _format_graph_attrs(self, attrs):
|
||||
return ''.join(['%s=%s;\n' % x for x in attrs.items()])
|
||||
|
||||
def generate_dot(self, name="dummy", urls={}, graph_attrs={}, node_attrs={}, edge_attrs={}):
|
||||
"""Generate a graphviz dot graph from the classes that were passed in
|
||||
to __init__.
|
||||
|
||||
*name* is the name of the graph.
|
||||
|
||||
*urls* is a dictionary mapping class names to HTTP URLs.
|
||||
|
||||
*graph_attrs*, *node_attrs*, *edge_attrs* are dictionaries containing
|
||||
key/value pairs to pass on as graphviz properties.
|
||||
"""
|
||||
|
||||
inheritance_graph_attrs = dict(fontsize=9, ratio='auto', size='""', rankdir="LR")
|
||||
inheritance_node_attrs = {"align": "center", 'shape': 'box',
|
||||
'fontsize': 10, 'height': 0.3,
|
||||
'fontname': 'Vera Sans, DejaVu Sans, Liberation Sans, '
|
||||
'Arial, Helvetica, sans', 'style': '"setlinewidth(0.5)"',
|
||||
'labelloc': 'c', 'fontcolor': 'grey45'}
|
||||
|
||||
inheritance_edge_attrs = {'arrowsize': 0.5, 'style': '"setlinewidth(0.5)"', "color": "black"}
|
||||
|
||||
g_attrs = self.default_graph_attrs.copy()
|
||||
n_attrs = self.default_node_attrs.copy()
|
||||
e_attrs = self.default_edge_attrs.copy()
|
||||
g_attrs.update(inheritance_graph_attrs)
|
||||
n_attrs.update(inheritance_node_attrs)
|
||||
e_attrs.update(inheritance_edge_attrs)
|
||||
|
||||
res = []
|
||||
res.append('digraph %s {\n' % name)
|
||||
res.append(self._format_graph_attrs(g_attrs))
|
||||
|
||||
for name, fullname, bases in self.class_info:
|
||||
# Write the node
|
||||
this_node_attrs = n_attrs.copy()
|
||||
|
||||
if fullname in self.specials:
|
||||
this_node_attrs['fontcolor'] = 'black'
|
||||
this_node_attrs['color'] = 'blue'
|
||||
this_node_attrs['style'] = 'bold'
|
||||
|
||||
if self.main_class is None:
|
||||
newname, fullname = Wx2Sphinx(name)
|
||||
else:
|
||||
newname = name
|
||||
|
||||
this_node_attrs['URL'] = '"%s.html"'%fullname
|
||||
res.append(' "%s" [%s];\n' %
|
||||
(newname, self._format_node_attrs(this_node_attrs)))
|
||||
|
||||
# Write the edges
|
||||
for base_name in bases:
|
||||
|
||||
this_edge_attrs = e_attrs.copy()
|
||||
if fullname in self.specials:
|
||||
this_edge_attrs['color'] = 'red'
|
||||
|
||||
if self.main_class is None:
|
||||
base_name, dummy = Wx2Sphinx(base_name)
|
||||
|
||||
res.append(' "%s" -> "%s" [%s];\n' %
|
||||
(base_name, newname,
|
||||
self._format_node_attrs(this_edge_attrs)))
|
||||
res.append('}\n')
|
||||
return ''.join(res)
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------- #
|
||||
|
||||
def MakeInheritanceDiagram(self):
|
||||
"""
|
||||
Actually generates the inheritance diagram as a PNG file plus the corresponding
|
||||
MAP file for mouse navigation over the inheritance boxes.
|
||||
|
||||
These two files are saved into the ``INHERITANCEROOT`` folder (see `sphinxtools/constants.py`
|
||||
for more information).
|
||||
|
||||
:rtype: `tuple`
|
||||
|
||||
:returns: a tuple containing the PNG file name and a string representing the content
|
||||
of the MAP file (with newlines stripped away).
|
||||
|
||||
.. note:: The MAP file is deleted as soon as its content has been read.
|
||||
"""
|
||||
|
||||
static_root = INHERITANCEROOT
|
||||
|
||||
if self.main_class is not None:
|
||||
filename = self.main_class.name
|
||||
else:
|
||||
dummy, filename = Wx2Sphinx(self.specials[0])
|
||||
|
||||
outfn = os.path.join(static_root, filename + '_inheritance.png')
|
||||
mapfile = outfn + '.map'
|
||||
|
||||
if os.path.isfile(outfn) and os.path.isfile(mapfile):
|
||||
fid = open(mapfile, 'rt')
|
||||
map = fid.read()
|
||||
fid.close()
|
||||
return os.path.split(outfn)[1], map.replace('\n', ' ')
|
||||
|
||||
code = self.generate_dot()
|
||||
|
||||
# graphviz expects UTF-8 by default
|
||||
if isinstance(code, unicode):
|
||||
code = code.encode('utf-8')
|
||||
|
||||
dot_args = ['dot']
|
||||
|
||||
if os.path.isfile(outfn):
|
||||
os.remove(outfn)
|
||||
if os.path.isfile(mapfile):
|
||||
os.remove(mapfile)
|
||||
|
||||
dot_args.extend(['-Tpng', '-o' + outfn])
|
||||
dot_args.extend(['-Tcmapx', '-o' + mapfile])
|
||||
|
||||
try:
|
||||
|
||||
p = Popen(dot_args, stdout=PIPE, stdin=PIPE, stderr=PIPE)
|
||||
|
||||
except OSError, err:
|
||||
|
||||
if err.errno != ENOENT: # No such file or directory
|
||||
raise
|
||||
|
||||
print '\nERROR: Graphviz command `dot` cannot be run (needed for Graphviz output), check your ``PATH`` setting'
|
||||
|
||||
try:
|
||||
# Graphviz may close standard input when an error occurs,
|
||||
# resulting in a broken pipe on communicate()
|
||||
stdout, stderr = p.communicate(code)
|
||||
|
||||
except OSError, err:
|
||||
|
||||
# in this case, read the standard output and standard error streams
|
||||
# directly, to get the error message(s)
|
||||
stdout, stderr = p.stdout.read(), p.stderr.read()
|
||||
p.wait()
|
||||
|
||||
if p.returncode != 0:
|
||||
print '\nERROR: Graphviz `dot` command exited with error:\n[stderr]\n%s\n[stdout]\n%s\n\n' % (stderr, stdout)
|
||||
|
||||
fid = open(mapfile, 'rt')
|
||||
map = fid.read()
|
||||
fid.close()
|
||||
|
||||
return os.path.split(outfn)[1], map.replace('\n', ' ')
|
||||
|
||||
735
sphinxtools/librarydescription.py
Normal file
735
sphinxtools/librarydescription.py
Normal file
@@ -0,0 +1,735 @@
|
||||
import sys
|
||||
import os
|
||||
import operator
|
||||
import errno
|
||||
import re
|
||||
|
||||
from StringIO import StringIO
|
||||
from subprocess import Popen, PIPE
|
||||
|
||||
from inspect import getmro, getclasstree, getdoc, getcomments
|
||||
|
||||
from utilities import MakeSummary, ChopDescription, WriteSphinxOutput, PickleClassInfo
|
||||
from constants import object_types, MODULE_TO_ICON
|
||||
import templates
|
||||
|
||||
ENOENT = getattr(errno, 'ENOENT', 0)
|
||||
EPIPE = getattr(errno, 'EPIPE', 0)
|
||||
|
||||
reload(sys)
|
||||
sys.setdefaultencoding("utf-8")
|
||||
|
||||
|
||||
def make_class_tree(tree):
|
||||
|
||||
class_tree = []
|
||||
|
||||
if isinstance(tree, list):
|
||||
for node in tree:
|
||||
class_tree.append(make_class_tree(node))
|
||||
else:
|
||||
name = tree[0].__name__
|
||||
class_tree.append(name)
|
||||
|
||||
return class_tree
|
||||
|
||||
|
||||
def generic_summary(libraryItem, stream):
|
||||
|
||||
write_toc = True
|
||||
add_tilde = [True, True]
|
||||
|
||||
if libraryItem.kind in [object_types.LIBRARY, object_types.PACKAGE]:
|
||||
list1 = libraryItem.GetItemByKind(object_types.PACKAGE)
|
||||
list2 = libraryItem.GetItemByKind(object_types.PY_MODULE, object_types.PYW_MODULE)
|
||||
|
||||
templ = [templates.TEMPLATE_PACKAGE_SUMMARY, templates.TEMPLATE_MODULE_SUMMARY]
|
||||
refs = ['mod', 'mod']
|
||||
|
||||
elif libraryItem.kind in range(object_types.PY_MODULE, object_types.PYW_MODULE+1):
|
||||
list1 = libraryItem.GetItemByKind(object_types.FUNCTION)
|
||||
list2 = libraryItem.GetItemByKind(object_types.KLASS, recurse=True)
|
||||
|
||||
templ = [templates.TEMPLATE_STD_FUNCTION_SUMMARY, templates.TEMPLATE_STD_CLASS_SUMMARY]
|
||||
refs = ['func', 'ref']
|
||||
add_tilde = [True, False]
|
||||
|
||||
elif libraryItem.kind == object_types.KLASS:
|
||||
write_toc = False
|
||||
list1 = libraryItem.GetItemByKind(object_types.METHOD, object_types.INSTANCE_METHOD)
|
||||
list2 = libraryItem.GetItemByKind(object_types.PROPERTY)
|
||||
|
||||
templ = [templates.TEMPLATE_METHOD_SUMMARY, templates.TEMPLATE_PROPERTY_SUMMARY]
|
||||
refs = ['meth', 'attr']
|
||||
add_tilde = [True, True]
|
||||
|
||||
else:
|
||||
raise Exception('Invalid library item: %s'%libraryItem.GetShortName())
|
||||
|
||||
toctree = ''
|
||||
|
||||
for index, sub_list in enumerate([list1, list2]):
|
||||
table = []
|
||||
for item in sub_list:
|
||||
|
||||
if item.is_redundant:
|
||||
continue
|
||||
|
||||
docs = ChopDescription(ReplaceWxDot(item.docs))
|
||||
table.append((item.name, docs))
|
||||
|
||||
if item.kind != object_types.FUNCTION:
|
||||
toctree += ' %s\n'%item.name
|
||||
|
||||
if table:
|
||||
summary = MakeSummary(table, templ[index], refs[index], add_tilde[index])
|
||||
stream.write(summary)
|
||||
|
||||
if toctree and write_toc:
|
||||
stream.write(templates.TEMPLATE_TOCTREE%toctree)
|
||||
stream.write('\n\n')
|
||||
|
||||
|
||||
def MakeSphinxFile(name):
|
||||
|
||||
return os.path.join(os.getcwd(), 'docs', 'sphinx', '%s.txt'%name)
|
||||
|
||||
|
||||
def ReplaceWxDot(text):
|
||||
|
||||
# Double ticks with 'wx.' in them
|
||||
text = re.sub(r'``wx\.(.*?)``', r'``\1`` ', text)
|
||||
|
||||
# Signle ticks with 'wx.' in them... try and referencing them
|
||||
text = re.sub(r'`wx\.(.*?)`', r'`\1` ', text)
|
||||
|
||||
return text
|
||||
|
||||
|
||||
class ParentBase(object):
|
||||
|
||||
def __init__(self, name, kind):
|
||||
|
||||
self.name = name
|
||||
self.kind = kind
|
||||
|
||||
self.docs = u''
|
||||
self.comments = u''
|
||||
|
||||
self.is_redundant = False
|
||||
|
||||
self.children = []
|
||||
|
||||
|
||||
def Add(self, klass):
|
||||
|
||||
if u'lambda' in klass.name:
|
||||
return
|
||||
|
||||
for child in self.children:
|
||||
if child.name == klass.name:
|
||||
return
|
||||
|
||||
klass.parent = self
|
||||
self.children.append(klass)
|
||||
|
||||
|
||||
def Save(self):
|
||||
|
||||
self.children = sorted(self.children, key=lambda k: (getattr(k, "order"), getattr(k, "name").lower()))
|
||||
|
||||
if self.docs is None:
|
||||
self.docs = u''
|
||||
|
||||
if self.comments is None or not self.comments.strip():
|
||||
self.comments = u''
|
||||
|
||||
for child in self.children:
|
||||
child.Save()
|
||||
|
||||
|
||||
def GetImage(self):
|
||||
|
||||
return self.kind
|
||||
|
||||
|
||||
def GetName(self):
|
||||
|
||||
return self.name
|
||||
|
||||
|
||||
def GetShortName(self):
|
||||
|
||||
return self.name.split(".")[-1]
|
||||
|
||||
|
||||
def GetObject(self):
|
||||
|
||||
return self.obj_type
|
||||
|
||||
|
||||
def GetChildren(self):
|
||||
|
||||
return self.children
|
||||
|
||||
|
||||
def GetChildrenCount(self, recursively=True):
|
||||
"""
|
||||
Gets the number of children of this item.
|
||||
|
||||
:param bool `recursively`: if ``True``, returns the total number of descendants,
|
||||
otherwise only one level of children is counted.
|
||||
"""
|
||||
|
||||
count = len(self.children)
|
||||
|
||||
if not recursively:
|
||||
return count
|
||||
|
||||
total = count
|
||||
|
||||
for n in xrange(count):
|
||||
total += self.children[n].GetChildrenCount()
|
||||
|
||||
return total
|
||||
|
||||
|
||||
def GetKindCount(self, minObj, maxObj=None):
|
||||
|
||||
if maxObj is None:
|
||||
maxObj = minObj
|
||||
|
||||
count = 0
|
||||
for child in self.children:
|
||||
if minObj <= child.kind <= maxObj:
|
||||
count += 1
|
||||
|
||||
return count
|
||||
|
||||
|
||||
def GetItemByKind(self, minObj, maxObj=None, recurse=False):
|
||||
|
||||
if maxObj is None:
|
||||
maxObj = minObj
|
||||
|
||||
items = []
|
||||
for child in self.children:
|
||||
if minObj <= child.kind <= maxObj:
|
||||
items.append(child)
|
||||
|
||||
if recurse:
|
||||
items = items + child.GetItemByKind(minObj, maxObj, recurse)
|
||||
|
||||
return items
|
||||
|
||||
|
||||
def ToRest(self):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class Library(ParentBase):
|
||||
|
||||
def __init__(self, name):
|
||||
|
||||
ParentBase.__init__(self, name, object_types.LIBRARY)
|
||||
|
||||
self.parent = None
|
||||
self.filename = u''
|
||||
self.order = 0
|
||||
self.obj_type = u"Library"
|
||||
self.python_version = u''
|
||||
|
||||
self.sphinx_file = MakeSphinxFile(name)
|
||||
self.base_name = name
|
||||
|
||||
|
||||
def GetShortName(self):
|
||||
|
||||
return self.name
|
||||
|
||||
|
||||
def Walk(self, obj):
|
||||
|
||||
if obj == self:
|
||||
obj.ToRest()
|
||||
|
||||
# must have at least root folder
|
||||
children = obj.GetChildren()
|
||||
|
||||
if not children:
|
||||
return
|
||||
|
||||
# check each name
|
||||
for child in children:
|
||||
|
||||
if child.is_redundant:
|
||||
continue
|
||||
|
||||
child.ToRest()
|
||||
|
||||
# recursively scan other folders, appending results
|
||||
self.Walk(child)
|
||||
|
||||
|
||||
def GetPythonVersion(self):
|
||||
|
||||
return self.python_version
|
||||
|
||||
|
||||
def ToRest(self):
|
||||
|
||||
print '\n\nReST-ifying %s...\n\n'%self.base_name
|
||||
stream = StringIO()
|
||||
|
||||
header = templates.TEMPLATE_DESCRIPTION%(self.base_name, self.base_name + ' Library')
|
||||
stream.write(header)
|
||||
|
||||
stream.write(ReplaceWxDot(self.docs) + '\n\n')
|
||||
|
||||
generic_summary(self, stream)
|
||||
WriteSphinxOutput(stream, self.sphinx_file)
|
||||
|
||||
|
||||
class Module(ParentBase):
|
||||
|
||||
def __init__(self, name, kind):
|
||||
|
||||
ParentBase.__init__(self, name, kind)
|
||||
|
||||
self.filename = u''
|
||||
self.sphinx_file = MakeSphinxFile(name)
|
||||
|
||||
if kind == object_types.PACKAGE:
|
||||
self.obj_type = u"Package"
|
||||
self.order = kind
|
||||
return
|
||||
|
||||
self.order = object_types.PY_MODULE
|
||||
|
||||
for dummy, icon, description in MODULE_TO_ICON:
|
||||
if icon == kind:
|
||||
self.obj_type = description
|
||||
break
|
||||
|
||||
self.inheritance_diagram = None
|
||||
|
||||
|
||||
def ToRest(self):
|
||||
|
||||
stream = StringIO()
|
||||
|
||||
label = 'Module'
|
||||
if self.kind == object_types.PACKAGE:
|
||||
label = 'Package'
|
||||
|
||||
stream.write('.. module:: %s\n\n'%self.name)
|
||||
stream.write('.. currentmodule:: %s\n\n'%self.name)
|
||||
|
||||
header = templates.TEMPLATE_DESCRIPTION%(self.name, '%s %s'%(self.name, label))
|
||||
|
||||
stream.write(header)
|
||||
stream.write(ReplaceWxDot(self.docs) + '\n\n')
|
||||
|
||||
spacer = ' '*self.name.count('.')
|
||||
|
||||
if self.kind != object_types.PACKAGE:
|
||||
print '%s - %s (module)'%(spacer, self.name)
|
||||
if self.inheritance_diagram:
|
||||
png, map = self.inheritance_diagram.MakeInheritanceDiagram()
|
||||
short_name = self.GetShortName()
|
||||
image_desc = templates.TEMPLATE_INHERITANCE % (short_name, png, short_name, map)
|
||||
stream.write(image_desc)
|
||||
else:
|
||||
print '%s - %s (package)'%(spacer, self.name)
|
||||
|
||||
generic_summary(self, stream)
|
||||
|
||||
if self.kind != object_types.PACKAGE:
|
||||
functions = self.GetItemByKind(object_types.FUNCTION)
|
||||
|
||||
count = 0
|
||||
for fun in functions:
|
||||
if not fun.is_redundant:
|
||||
count = 1
|
||||
break
|
||||
|
||||
if count > 0:
|
||||
stream.write('\n\nFunctions\n===========\n\n')
|
||||
|
||||
for fun in functions:
|
||||
if fun.is_redundant:
|
||||
continue
|
||||
fun.Write(stream)
|
||||
|
||||
WriteSphinxOutput(stream, self.sphinx_file)
|
||||
|
||||
|
||||
|
||||
class Class(ParentBase):
|
||||
|
||||
def __init__(self, name, obj):
|
||||
|
||||
ParentBase.__init__(self, name, object_types.KLASS)
|
||||
|
||||
try:
|
||||
subs = obj.__subclasses__()
|
||||
except (AttributeError, TypeError):
|
||||
subs = []
|
||||
|
||||
sups = list(obj.__bases__)
|
||||
|
||||
sortedSubClasses = []
|
||||
sortedSupClasses = []
|
||||
|
||||
for item in sups:
|
||||
item = repr(item)
|
||||
|
||||
sup = item.replace("<class ", "").replace(">", "").replace("<type ", "")
|
||||
sup = sup.strip().replace('"', "").replace("'", "")
|
||||
if " at " in sup:
|
||||
sup = sup[0:sup.index(" at ")].strip()
|
||||
|
||||
if 'wx._' in sup:
|
||||
name_parts = sup.split('.')
|
||||
sup = name_parts[-1]
|
||||
|
||||
sortedSupClasses.append(sup)
|
||||
|
||||
sortedSupClasses.sort()
|
||||
|
||||
for s in subs:
|
||||
s = repr(s)
|
||||
|
||||
if "'" in s:
|
||||
start = s.index("'")
|
||||
end = s.rindex("'")
|
||||
cls = s[start+1:end]
|
||||
else:
|
||||
cls = s
|
||||
|
||||
if 'wx._' in cls:
|
||||
name_parts = cls.split('.')
|
||||
cls = name_parts[-1]
|
||||
|
||||
sortedSubClasses.append(cls)
|
||||
|
||||
sortedSubClasses.sort()
|
||||
|
||||
self.class_tree = make_class_tree(getclasstree(getmro(obj)))
|
||||
|
||||
self.subClasses = sortedSubClasses
|
||||
self.superClasses = sortedSupClasses
|
||||
|
||||
self.signature = ""
|
||||
self.inheritance_diagram = None
|
||||
|
||||
self.order = 3
|
||||
self.obj_type = u"Class"
|
||||
self.sphinx_file = MakeSphinxFile(name)
|
||||
|
||||
|
||||
def ToRest(self):
|
||||
|
||||
if self.is_redundant:
|
||||
return
|
||||
|
||||
stream = StringIO()
|
||||
|
||||
parts = self.name.split('.')
|
||||
current_module = '.'.join(parts[0:-1])
|
||||
|
||||
stream.write('.. currentmodule:: %s\n\n'%current_module)
|
||||
|
||||
header = templates.TEMPLATE_DESCRIPTION%(self.name, self.GetShortName())
|
||||
stream.write(header)
|
||||
stream.write(ReplaceWxDot(self.docs) + '\n\n')
|
||||
|
||||
if self.inheritance_diagram:
|
||||
png, map = self.inheritance_diagram.MakeInheritanceDiagram()
|
||||
short_name = self.GetShortName()
|
||||
image_desc = templates.TEMPLATE_INHERITANCE % (short_name, png, short_name, map)
|
||||
stream.write(image_desc)
|
||||
|
||||
if self.subClasses:
|
||||
subs = [':ref:`%s`'%cls for cls in self.superClasses]
|
||||
subs = ', '.join(subs)
|
||||
subs_desc = templates.TEMPLATE_SUBCLASSES % subs
|
||||
stream.write(subs_desc)
|
||||
|
||||
if self.superClasses:
|
||||
subs = [':ref:`%s`'%cls for cls in self.superClasses]
|
||||
subs = ', '.join(subs)
|
||||
subs_desc = templates.TEMPLATE_SUPERCLASSES % subs
|
||||
stream.write(subs_desc)
|
||||
|
||||
generic_summary(self, stream)
|
||||
|
||||
stream.write(templates.TEMPLATE_API)
|
||||
stream.write("\n.. class:: %s\n\n\n"%self.signature)
|
||||
|
||||
methods = self.GetItemByKind(object_types.METHOD, object_types.INSTANCE_METHOD)
|
||||
properties = self.GetItemByKind(object_types.PROPERTY)
|
||||
method_list = []
|
||||
|
||||
for meth in methods:
|
||||
meth.Write(stream)
|
||||
if not meth.is_redundant:
|
||||
method_list.append((meth.GetShortName(), ''))
|
||||
|
||||
for prop in properties:
|
||||
prop.Write(stream, short_name)
|
||||
|
||||
WriteSphinxOutput(stream, self.sphinx_file)
|
||||
|
||||
self.bases = self.superClasses
|
||||
self.method_list = method_list
|
||||
|
||||
PickleClassInfo(self.name, self)
|
||||
|
||||
|
||||
def Save(self):
|
||||
|
||||
ParentBase.Save(self)
|
||||
pop = -1
|
||||
|
||||
for index, child in enumerate(self.children):
|
||||
name = child.GetShortName()
|
||||
if name == '__init__':
|
||||
pop = index
|
||||
break
|
||||
|
||||
if pop >= 0:
|
||||
init = self.children.pop(pop)
|
||||
self.children.insert(0, init)
|
||||
|
||||
self.signature = self.signature.replace('wx.', '')
|
||||
self.signature = self.signature.rstrip(':').lstrip('class ')
|
||||
|
||||
if ' def __init__' in self.signature:
|
||||
index = self.signature.index(' def __init__')
|
||||
self.signature = self.signature[0:index]
|
||||
|
||||
self.signature.strip()
|
||||
|
||||
|
||||
class ChildrenBase(object):
|
||||
|
||||
def __init__(self, name, kind):
|
||||
|
||||
self.name = name
|
||||
self.kind = kind
|
||||
|
||||
self.order = 4
|
||||
|
||||
self.docs = u''
|
||||
self.comments = u''
|
||||
|
||||
self.is_redundant = False
|
||||
|
||||
## self.id = NewId()
|
||||
|
||||
|
||||
def GetImage(self):
|
||||
|
||||
return self.kind
|
||||
|
||||
|
||||
def GetName(self):
|
||||
|
||||
return self.name
|
||||
|
||||
|
||||
def GetShortName(self):
|
||||
|
||||
return self.name.split(".")[-1]
|
||||
|
||||
|
||||
def GetChildren(self):
|
||||
|
||||
return []
|
||||
|
||||
|
||||
def GetChildrenCount(self, recursively=True):
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def GetObject(self):
|
||||
|
||||
return self.obj_type
|
||||
|
||||
|
||||
def Save(self):
|
||||
|
||||
if self.docs is None:
|
||||
self.docs = u''
|
||||
|
||||
if self.comments is None or not self.comments.strip():
|
||||
self.comments = u''
|
||||
|
||||
|
||||
def ToRest(self):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class Method(ChildrenBase):
|
||||
|
||||
def __init__(self, name, kind):
|
||||
|
||||
ChildrenBase.__init__(self, name, kind)
|
||||
|
||||
self.order = 5
|
||||
|
||||
self.arguments = []
|
||||
self.signature = u''
|
||||
|
||||
self.obj_type = u"Method/Function"
|
||||
|
||||
|
||||
def Save(self):
|
||||
|
||||
ChildrenBase.Save(self)
|
||||
|
||||
newargs = []
|
||||
if self.arguments and any(self.arguments[0]):
|
||||
for name, repr_val, eval_val in self.arguments:
|
||||
repr_val = (repr_val is not None and [repr_val] or [""])[0]
|
||||
eval_val = (eval_val is not None and [eval_val] or [""])[0]
|
||||
newargs.append((name, repr_val, eval_val))
|
||||
|
||||
self.arguments = newargs
|
||||
|
||||
self.signature = self.signature.replace('wx.', '')
|
||||
self.signature = self.signature.rstrip(':').lstrip()
|
||||
|
||||
if self.signature.startswith('def '):
|
||||
self.signature = self.signature[4:]
|
||||
|
||||
if not self.signature.strip():
|
||||
self.is_redundant = True
|
||||
|
||||
|
||||
def Write(self, stream):
|
||||
|
||||
if self.is_redundant:
|
||||
return
|
||||
|
||||
if self.kind == object_types.FUNCTION:
|
||||
stream.write('.. function:: %s\n\n'%self.signature)
|
||||
indent = 3*' '
|
||||
else:
|
||||
stream.write(' .. method:: %s\n\n'%self.signature)
|
||||
indent = 6*' '
|
||||
|
||||
if not self.docs.strip():
|
||||
stream.write('\n')
|
||||
return
|
||||
|
||||
text = ''
|
||||
for line in self.docs.splitlines():
|
||||
text += indent + ReplaceWxDot(line) + '\n'
|
||||
|
||||
text += '\n\n'
|
||||
stream.write(text)
|
||||
|
||||
|
||||
|
||||
class Property(ChildrenBase):
|
||||
|
||||
def __init__(self, name, item):
|
||||
|
||||
ChildrenBase.__init__(self, name, object_types.PROPERTY)
|
||||
|
||||
self.getter = self.setter = self.deleter = ""
|
||||
|
||||
try:
|
||||
if item.fget:
|
||||
self.getter = item.fget.__name__
|
||||
if item.fset:
|
||||
self.setter = item.fset.__name__
|
||||
if item.fdel:
|
||||
self.deleter = item.fdel.__name__
|
||||
except AttributeError:
|
||||
# Thank you for screwing it up, Cython...
|
||||
if item.fget:
|
||||
self.getter = item.fget.__class__.__name__
|
||||
if item.fset:
|
||||
self.setter = item.fset.__class__.__name__
|
||||
if item.fdel:
|
||||
self.deleter = item.fdel.__class__.__name__
|
||||
|
||||
self.docs = getdoc(item)
|
||||
self.comments = getcomments(item)
|
||||
|
||||
self.obj_type = u"Property"
|
||||
self.order = 6
|
||||
|
||||
|
||||
def Write(self, stream, class_name):
|
||||
|
||||
if self.is_redundant:
|
||||
return
|
||||
|
||||
docs = ''
|
||||
for item in [self.setter, self.getter, self.deleter]:
|
||||
if item and 'lambda' not in item and not item.startswith('_'):
|
||||
if docs:
|
||||
docs += ', :meth:`~%s.%s` '%(class_name, item)
|
||||
else:
|
||||
docs += ':meth:`~%s.%s` '%(class_name, item)
|
||||
|
||||
if docs:
|
||||
docs = 'See %s'%docs
|
||||
|
||||
stream.write(' .. attribute:: %s\n\n'%self.GetShortName())
|
||||
stream.write(' %s\n\n\n'%docs)
|
||||
|
||||
|
||||
class Attribute(ChildrenBase):
|
||||
|
||||
def __init__(self, name, specs, value):
|
||||
|
||||
specs = unicode(specs)
|
||||
start, end = specs.find("'"), specs.rfind("'")
|
||||
specs = specs[start+1:end]
|
||||
|
||||
strValue = repr(value)
|
||||
uspecs = specs.upper()
|
||||
|
||||
try:
|
||||
kind = getattr(object_types, uspecs)
|
||||
except AttributeError:
|
||||
try:
|
||||
uspecs = uspecs + u"TYPE"
|
||||
kind = getattr(object_types, uspecs)
|
||||
except AttributeError:
|
||||
kind = object_types.UNKNOWNTYPE
|
||||
|
||||
try:
|
||||
reprValue = repr(value.__class__)
|
||||
except (NameError, AttributeError):
|
||||
reprValue = ""
|
||||
|
||||
if u"class" in strValue or u"class" in reprValue:
|
||||
kind = object_types.INSTANCETYPE
|
||||
|
||||
ChildrenBase.__init__(self, name, kind)
|
||||
|
||||
self.value = strValue
|
||||
self.specs = specs
|
||||
|
||||
try:
|
||||
self.docs = getdoc(value)
|
||||
except (NameError, AttributeError):
|
||||
self.docs = u''
|
||||
|
||||
self.obj_type = u"Attribute"
|
||||
self.order = 7
|
||||
|
||||
|
||||
def ToRest(self):
|
||||
|
||||
pass
|
||||
|
||||
632
sphinxtools/modulehunter.py
Normal file
632
sphinxtools/modulehunter.py
Normal file
@@ -0,0 +1,632 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Describe classes, methods and functions in a module.
|
||||
# Works with user-defined modules, all Python library
|
||||
# modules, including built-in modules.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import glob
|
||||
import types
|
||||
import cPickle
|
||||
import imp
|
||||
import traceback
|
||||
import pkgutil
|
||||
|
||||
import __builtin__
|
||||
|
||||
from inspect import getargspec, ismodule, getdoc, getmodule, getcomments, isfunction
|
||||
from inspect import ismethoddescriptor, getsource, ismemberdescriptor, isgetsetdescriptor
|
||||
from inspect import isbuiltin, isclass, getfile, ismethod
|
||||
|
||||
from librarydescription import Library, Module, Class
|
||||
from librarydescription import Method, Property, Attribute
|
||||
|
||||
import inheritance
|
||||
|
||||
from constants import object_types, EXCLUDED_ATTRS, MODULE_TO_ICON
|
||||
from constants import CONSTANT_RE
|
||||
|
||||
reload(sys)
|
||||
sys.setdefaultencoding("utf-8")
|
||||
|
||||
try:
|
||||
import wx
|
||||
except ImportError:
|
||||
wxPath = None
|
||||
for path in sys.path:
|
||||
if 'wx-' in path:
|
||||
wxPath = path
|
||||
break
|
||||
|
||||
if wxPath is None:
|
||||
raise Exception('Unable to find the wx package')
|
||||
|
||||
sys.path.insert(0, wxPath)
|
||||
|
||||
import wx
|
||||
|
||||
|
||||
if hasattr(os.path, "relpath"):
|
||||
relpath = os.path.relpath # since Python 2.6
|
||||
else:
|
||||
def relpath(path, start=os.path.curdir):
|
||||
"""Return a relative version of a path"""
|
||||
|
||||
if not path:
|
||||
raise ValueError("no path specified")
|
||||
|
||||
start_list = os.path.abspath(start).split(os.path.sep)
|
||||
path_list = os.path.abspath(path).split(os.path.sep)
|
||||
|
||||
# Work out how much of the filepath is shared by start and path.
|
||||
i = len(os.path.commonprefix([start_list, path_list]))
|
||||
|
||||
rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
|
||||
if not rel_list:
|
||||
return os.path.curdir
|
||||
|
||||
return os.path.join(*rel_list)
|
||||
|
||||
|
||||
def format_traceback():
|
||||
|
||||
t, v = sys.exc_info()[:2]
|
||||
message = "".join(traceback.format_exception_only(t, v)).replace("\n", " ")
|
||||
return message.strip()
|
||||
|
||||
|
||||
def format_method(method):
|
||||
|
||||
method = method.strip()
|
||||
|
||||
if "def " not in method:
|
||||
return None, None
|
||||
|
||||
indx1, indx2, indx3 = method.index("def "), method.index("("), method.rindex(")")
|
||||
name = method[indx1+4:indx2]
|
||||
signature = method[indx2+1:indx3]
|
||||
|
||||
if "\n" in signature:
|
||||
sig = signature.split("\n")
|
||||
params = ""
|
||||
for s in sig:
|
||||
params += s.strip() + " "
|
||||
params = params.rstrip()
|
||||
else:
|
||||
params = signature
|
||||
|
||||
return name, params
|
||||
|
||||
|
||||
def analyze_params(obj, signature):
|
||||
|
||||
params = signature.split(",")
|
||||
if "self" in params:
|
||||
params.remove("self")
|
||||
signature = ",".join(params)
|
||||
|
||||
param_tuple = []
|
||||
|
||||
if not params:
|
||||
return signature, param_tuple
|
||||
|
||||
try:
|
||||
arginfo = getargspec(obj)
|
||||
except TypeError:
|
||||
arginfo = None
|
||||
|
||||
pevals = {}
|
||||
|
||||
if arginfo:
|
||||
args = arginfo[0]
|
||||
argsvar = arginfo[1]
|
||||
|
||||
if arginfo[3]:
|
||||
|
||||
dl = len(arginfo[3])
|
||||
al = len(args)
|
||||
defargs = args[al-dl:al]
|
||||
info = arginfo[3]
|
||||
|
||||
for d, i in zip(defargs, info):
|
||||
pevals[d] = i
|
||||
|
||||
for par in params:
|
||||
p = par.strip()
|
||||
pvalue = peval = None
|
||||
|
||||
if "=" in p:
|
||||
all_values = p.split("=")
|
||||
pname, pvalue = all_values[0].strip(), "=".join(all_values[1:]).strip()
|
||||
pvalue = pvalue.strip()
|
||||
if pname in pevals:
|
||||
try:
|
||||
peval = unicode(pevals[pname])
|
||||
except UnicodeDecodeError:
|
||||
peval = repr(pevals[pname])
|
||||
except TypeError:
|
||||
peval = u''
|
||||
else:
|
||||
pname = p
|
||||
|
||||
param_tuple.append((pname, pvalue, peval))
|
||||
|
||||
return signature, param_tuple
|
||||
|
||||
|
||||
def get_constructor(source):
|
||||
|
||||
description = ""
|
||||
hasComma = False
|
||||
|
||||
for line in source.split("\n"):
|
||||
|
||||
if '#' in line:
|
||||
line = line[0:line.index('#')].strip()
|
||||
|
||||
if ":" in line:
|
||||
hasComma = True
|
||||
commaPos = line.index(":")
|
||||
|
||||
if ('"""' in line or "'''" in line) and hasComma:
|
||||
break
|
||||
|
||||
if hasComma and ' def ' in line:
|
||||
defPos = line.index(' def ')
|
||||
if defPos > commaPos:
|
||||
break
|
||||
|
||||
description += " " + line.strip()
|
||||
|
||||
if "):" in line or ") :" in line or ") :" in line:
|
||||
break
|
||||
|
||||
return description
|
||||
|
||||
|
||||
def inspect_source(method_class, obj, source):
|
||||
|
||||
description = get_constructor(source)
|
||||
name, params = format_method(description)
|
||||
|
||||
if name is None:
|
||||
return
|
||||
|
||||
signature, param_tuple = analyze_params(obj, params)
|
||||
|
||||
method_class.arguments = param_tuple
|
||||
method_class.signature = description.strip()
|
||||
|
||||
if "classmethod " in description or is_classmethod(obj):
|
||||
method_class.kind = object_types.CLASS_METHOD
|
||||
elif "staticmethod " in description:
|
||||
method_class.kind = object_types.STATIC_METHOD
|
||||
|
||||
|
||||
def is_classmethod(instancemethod):
|
||||
" Determine if an instancemethod is a classmethod. "
|
||||
|
||||
if hasattr(instancemethod, 'im_self'):
|
||||
return instancemethod.im_self is not None
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def describe_func(obj, parent_class, module_name):
|
||||
"""
|
||||
Describe the function object passed as argument.
|
||||
If this is a method object, the second argument will
|
||||
be passed as True.
|
||||
"""
|
||||
|
||||
try:
|
||||
name = obj.__name__
|
||||
except AttributeError:
|
||||
# Funny comtypes...
|
||||
return
|
||||
|
||||
if name.startswith("_") and "__init__" not in name:
|
||||
return
|
||||
|
||||
name = parent_class.name + "." + name
|
||||
|
||||
docs = getdoc(obj)
|
||||
comments = getcomments(obj)
|
||||
|
||||
if isfunction(obj):
|
||||
method = object_types.FUNCTION
|
||||
elif ismethod(obj):
|
||||
method = object_types.METHOD
|
||||
elif ismethoddescriptor(obj):
|
||||
method = object_types.METHOD_DESCRIPTOR
|
||||
|
||||
if isinstance(obj, types.MethodType):
|
||||
method = object_types.INSTANCE_METHOD
|
||||
|
||||
try:
|
||||
source_code = getsource(obj)
|
||||
except (IOError, TypeError):
|
||||
source_code = ""
|
||||
|
||||
klass = Method(name, method)
|
||||
klass.docs = docs
|
||||
|
||||
klass_module = getmodule(obj)
|
||||
if klass_module and klass_module.__name__ != module_name:
|
||||
klass.is_redundant = True
|
||||
|
||||
if source_code:
|
||||
inspect_source(klass, obj, source_code)
|
||||
klass.number_lines = "%d"%len(source_code.split("\n"))
|
||||
|
||||
if isinstance(obj, staticmethod):
|
||||
klass.method = method = object_types.STATIC_METHOD
|
||||
|
||||
try:
|
||||
if method in [object_types.METHOD, object_types.METHOD_DESCRIPTOR, object_types.INSTANCE_METHOD]:
|
||||
code = obj.im_func.func_code
|
||||
elif method == object_types.STATIC_METHOD:
|
||||
code = obj.im_func.func_code
|
||||
else:
|
||||
code = obj.func_code
|
||||
except AttributeError:
|
||||
code = None
|
||||
|
||||
if code is not None:
|
||||
klass.firstlineno = "%d"%code.co_firstlineno
|
||||
|
||||
parent_class.Add(klass)
|
||||
|
||||
|
||||
def describe_class(obj, module_class, module_name, constants):
|
||||
"""
|
||||
Describe the class object passed as argument,
|
||||
including its methods.
|
||||
"""
|
||||
|
||||
class_name = obj.__name__
|
||||
|
||||
if class_name == "object":
|
||||
return
|
||||
|
||||
class_name = module_class.name + "." + class_name
|
||||
|
||||
docs = getdoc(obj)
|
||||
comments = getcomments(obj)
|
||||
|
||||
obj_dict = obj.__dict__
|
||||
|
||||
klass = Class(class_name, obj)
|
||||
|
||||
count = 0
|
||||
|
||||
for name in obj_dict:
|
||||
|
||||
if name.startswith("_") and "__init__" not in name:
|
||||
continue
|
||||
|
||||
if name in EXCLUDED_ATTRS:
|
||||
continue
|
||||
|
||||
try:
|
||||
item = getattr(obj, name)
|
||||
except AttributeError:
|
||||
# Thanks to ReportLab for this funny exception...
|
||||
continue
|
||||
|
||||
if ismodule(item):
|
||||
continue
|
||||
|
||||
if ismemberdescriptor(item) or isgetsetdescriptor(item):
|
||||
continue
|
||||
|
||||
if isbuiltin(item):
|
||||
count += 1
|
||||
elif ismethod(item) or isfunction(item) or ismethoddescriptor(item) or \
|
||||
isinstance(item, types.MethodType):
|
||||
count += 1
|
||||
describe_func(item, klass, module_name)
|
||||
elif isclass(item):
|
||||
count += 1
|
||||
describe_class(item, klass, module_name, constants)
|
||||
else:
|
||||
name = class_name + "." + name
|
||||
if isinstance(item, property):
|
||||
item_class = Property(name, item)
|
||||
klass.Add(item_class)
|
||||
|
||||
item_module = getmodule(obj)
|
||||
if item_module and item_module.__name__ != module_name:
|
||||
item_class.is_redundant = True
|
||||
|
||||
else:
|
||||
item_class = Attribute(name, type(item), item)
|
||||
klass.Add(item_class)
|
||||
|
||||
if constants:
|
||||
item_class.is_redundant = name not in constants
|
||||
|
||||
count += 1
|
||||
|
||||
klass.docs = docs
|
||||
klass.comments = comments
|
||||
|
||||
klass_module = getmodule(obj)
|
||||
if klass_module and klass_module.__name__ != module_name:
|
||||
klass.is_redundant = True
|
||||
else:
|
||||
klass.inheritance_diagram = inheritance.InheritanceDiagram([obj], klass)
|
||||
|
||||
module_class.Add(klass)
|
||||
|
||||
try:
|
||||
source_code = getsource(obj)
|
||||
except (IOError, TypeError):
|
||||
source_code = ""
|
||||
|
||||
if source_code:
|
||||
description = get_constructor(source_code)
|
||||
klass.signature = description.strip()
|
||||
klass.number_lines = '%d'%len(source_code.split("\n"))
|
||||
|
||||
|
||||
def describe_module(module, kind, constants=[]):
|
||||
"""
|
||||
Describe the module object passed as argument
|
||||
including its classes and functions.
|
||||
"""
|
||||
|
||||
module_name = module.__name__
|
||||
|
||||
if kind == object_types.LIBRARY:
|
||||
klass = Library(module_name)
|
||||
else:
|
||||
klass = Module(module_name, kind)
|
||||
|
||||
klass.docs = getdoc(module)
|
||||
klass.comments = getcomments(module)
|
||||
|
||||
klass.filename = module.__file__
|
||||
inheritance_diagram = []
|
||||
|
||||
count = 0
|
||||
|
||||
for name in dir(module):
|
||||
|
||||
if name in EXCLUDED_ATTRS:
|
||||
continue
|
||||
|
||||
obj = getattr(module, name)
|
||||
|
||||
if ismodule(obj):
|
||||
continue
|
||||
|
||||
if ismemberdescriptor(obj) or isgetsetdescriptor(obj):
|
||||
continue
|
||||
|
||||
if isclass(obj):
|
||||
count += 1
|
||||
describe_class(obj, klass, module_name, constants)
|
||||
|
||||
if obj.__module__ == module.__name__:
|
||||
inheritance_diagram.append(obj)
|
||||
|
||||
elif isbuiltin(obj):
|
||||
count += 1
|
||||
elif ismethod(obj) or isfunction(obj) or ismethoddescriptor(obj) or \
|
||||
isinstance(obj, types.MethodType):
|
||||
count +=1
|
||||
describe_func(obj, klass, module_name)
|
||||
else:
|
||||
attribute = Attribute(module_name + "." + name, type(obj), obj)
|
||||
klass.Add(attribute)
|
||||
|
||||
if constants:
|
||||
attribute.is_redundant = name not in constants
|
||||
|
||||
if kind not in [object_types.PACKAGE, object_types.LIBRARY]:
|
||||
if inheritance_diagram and len(inheritance_diagram) < 20:
|
||||
klass.inheritance_diagram = inheritance.InheritanceDiagram(inheritance_diagram, klass)
|
||||
|
||||
return klass, count
|
||||
|
||||
|
||||
def Import(init_name, import_name, full_process=True):
|
||||
|
||||
directory, module_name = os.path.split(init_name)
|
||||
dirname = os.path.dirname(directory)
|
||||
|
||||
if not full_process:
|
||||
path = list(sys.path)
|
||||
sys.path.insert(0, dirname)
|
||||
|
||||
f = None
|
||||
|
||||
try:
|
||||
|
||||
f, filename, description = imp.find_module(import_name, [dirname])
|
||||
mainmod = imp.load_module(import_name, f, filename, description)
|
||||
|
||||
except (ImportError, NameError):
|
||||
|
||||
message = format_traceback()
|
||||
message += ' Please check that the "Import command" text box is correctly filled'
|
||||
print "Error: %s"%message
|
||||
|
||||
if not full_process:
|
||||
sys.path = path[:]
|
||||
|
||||
return
|
||||
|
||||
if f:
|
||||
f.close()
|
||||
|
||||
if not full_process:
|
||||
sys.path = path[:]
|
||||
try:
|
||||
version = mainmod.__version__
|
||||
except AttributeError:
|
||||
try:
|
||||
version = mainmod.__VERSION__
|
||||
except AttributeError:
|
||||
print "Warning: Library '%s' has no __version__ or __VERSION__ attribute. Please specify it in the 'Import command' textbox"%import_name
|
||||
return
|
||||
|
||||
print version
|
||||
|
||||
return mainmod
|
||||
|
||||
|
||||
def PrintProgress(name, looped_names):
|
||||
|
||||
looped_names.append(name)
|
||||
if len(looped_names) == 5:
|
||||
message = ", ".join(looped_names)
|
||||
looped_names = []
|
||||
print message
|
||||
|
||||
return looped_names
|
||||
|
||||
|
||||
|
||||
def FindModuleType(filename):
|
||||
|
||||
splitext = os.path.splitext(filename)[0]
|
||||
for extension, icon, description in MODULE_TO_ICON:
|
||||
if os.path.isfile(splitext + extension):
|
||||
return icon
|
||||
|
||||
|
||||
def SubImport(import_string, module, parent_class, ispkg):
|
||||
|
||||
try:
|
||||
submod = __import__(import_string, fromlist=[module])
|
||||
except:
|
||||
# pubsub and Editra can be funny sometimes...
|
||||
message = "Unable to import module/package '%s'.\n Exception was: %s"%(module, format_traceback())
|
||||
print "\nWARNING: %s\n"%message
|
||||
return None, 0
|
||||
|
||||
if not ismodule(submod):
|
||||
return None, 0
|
||||
|
||||
filename = getfile(submod)
|
||||
|
||||
if ispkg:
|
||||
kind = object_types.PACKAGE
|
||||
else:
|
||||
kind = FindModuleType(filename)
|
||||
|
||||
constants = []
|
||||
|
||||
if kind in [object_types.PY_MODULE, object_types.PACKAGE]:
|
||||
|
||||
contents = open(filename, "rt").read()
|
||||
consts = CONSTANT_RE.findall(contents)
|
||||
|
||||
for c in consts:
|
||||
if "," in c:
|
||||
c = c.split(",")
|
||||
constants.extend([v.strip() for v in c])
|
||||
else:
|
||||
constants.append(c.strip())
|
||||
|
||||
module_class, count = describe_module(submod, kind=kind, constants=constants)
|
||||
parent_class.Add(module_class)
|
||||
|
||||
return module_class, count
|
||||
|
||||
|
||||
def ModuleHunter(init_name, import_name, version):
|
||||
|
||||
pickle_file = os.path.join(os.getcwd(), 'docs', 'sphinx', 'wxlib.pkl')
|
||||
|
||||
if os.path.isfile(pickle_file):
|
||||
fid = open(pickle_file, 'rb')
|
||||
library_class = cPickle.load(fid)
|
||||
fid.close()
|
||||
library_class.Walk(library_class)
|
||||
return
|
||||
|
||||
path = list(sys.path)
|
||||
|
||||
directory, module_name = os.path.split(init_name)
|
||||
path = list(sys.path)
|
||||
|
||||
sys.path.insert(0, os.path.dirname(directory))
|
||||
|
||||
mainmod = Import(init_name, import_name)
|
||||
|
||||
if mainmod is None:
|
||||
return
|
||||
|
||||
message = "Importing main library '%s'..."%import_name
|
||||
print "Message: %s"%message
|
||||
|
||||
module_name = os.path.splitext(getfile(mainmod))[0] + ".py"
|
||||
contents = open(module_name, "rt").read()
|
||||
constants = CONSTANT_RE.findall(contents)
|
||||
|
||||
library_class, count = describe_module(mainmod, kind=object_types.LIBRARY, constants=constants)
|
||||
library_class.name = "%s-%s"%(import_name, version)
|
||||
|
||||
message = "Main library '%s' imported..."%library_class.name
|
||||
print "Message: %s"%message
|
||||
|
||||
message = "Importing sub-modules and sub-packages...\n"
|
||||
print "Message: %s"%message
|
||||
|
||||
looped_names = []
|
||||
ancestors_dict = {import_name: library_class}
|
||||
|
||||
for importer, module_name, ispkg in pkgutil.walk_packages(path=[directory],
|
||||
prefix=import_name+".",
|
||||
onerror=lambda x: None):
|
||||
|
||||
import_string = module_name
|
||||
splitted = module_name.split(".")
|
||||
|
||||
fromlist = splitted[-1]
|
||||
parent_name = ".".join(splitted[0:-1])
|
||||
|
||||
parent_class = ancestors_dict[parent_name]
|
||||
module_class, count = SubImport(import_string, fromlist, parent_class, ispkg)
|
||||
|
||||
if module_class is None:
|
||||
continue
|
||||
|
||||
looped_names = PrintProgress(module_name, looped_names)
|
||||
|
||||
if module_name not in ancestors_dict:
|
||||
ancestors_dict[module_name] = module_class
|
||||
|
||||
major, minor, micro, release = sys.version_info[0:-1]
|
||||
pythonVersion = u"%d.%d.%d-%s"%(major, minor, micro, release)
|
||||
|
||||
library_class.python_version = pythonVersion
|
||||
library_class.Save()
|
||||
|
||||
sys.path[:] = path # restore
|
||||
|
||||
fid = open(pickle_file, 'wb')
|
||||
cPickle.dump(library_class, fid)
|
||||
fid.close()
|
||||
|
||||
library_class.Walk(library_class)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
argv = sys.argv[1:]
|
||||
|
||||
if len(argv) == 2:
|
||||
init_name, import_name = argv
|
||||
Import(init_name, import_name, full_process=False)
|
||||
else:
|
||||
init_name, import_name, version, save_dir = argv
|
||||
ModuleHunter(init_name, import_name, version, save_dir)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ def SphinxIndexes(sphinxDir):
|
||||
if file.endswith('functions.pkl'):
|
||||
ReformatFunctions(file)
|
||||
elif 'classindex' in file:
|
||||
MakeClassIndex(file)
|
||||
MakeClassIndex(sphinxDir, file)
|
||||
|
||||
BuildEnumsAndMethods(sphinxDir)
|
||||
|
||||
@@ -122,9 +122,10 @@ def BuildEnumsAndMethods(sphinxDir):
|
||||
|
||||
if widget_name in SECTIONS_EXCLUDE:
|
||||
start, end = SECTIONS_EXCLUDE[widget_name]
|
||||
lindex = text.index(start)
|
||||
rindex = text.index(end)
|
||||
text = text[0:lindex] + text[rindex:]
|
||||
if start in text and end in text:
|
||||
lindex = text.index(start)
|
||||
rindex = text.index(end)
|
||||
text = text[0:lindex] + text[rindex:]
|
||||
|
||||
# Replace the "Perl Note" stuff, we don't need it
|
||||
newtext = ''
|
||||
@@ -361,7 +362,7 @@ def ReformatFunctions(file):
|
||||
|
||||
# ----------------------------------------------------------------------- #
|
||||
|
||||
def MakeClassIndex(file):
|
||||
def MakeClassIndex(sphinxDir, file):
|
||||
|
||||
text_file = os.path.splitext(file)[0] + '.txt'
|
||||
local_file = os.path.split(file)[1]
|
||||
@@ -376,13 +377,24 @@ def MakeClassIndex(file):
|
||||
if local_file.count('.') == 1:
|
||||
# Core functions
|
||||
label = 'Core'
|
||||
module = ''
|
||||
enumDots = 1
|
||||
else:
|
||||
label = local_file.split('.')[0:-2][0]
|
||||
module = label
|
||||
enumDots = 2
|
||||
|
||||
enum_files = glob.glob(sphinxDir + '/%s*.enumeration.txt'%module)
|
||||
enum_base = [os.path.split(os.path.splitext(enum)[0])[1] for enum in enum_files]
|
||||
|
||||
names = classes.keys()
|
||||
names.sort()
|
||||
|
||||
text = templates.TEMPLATE_CLASS_INDEX % (label, label)
|
||||
text = ''
|
||||
if module:
|
||||
text += '\n\n.. module:: %s\n\n'%module
|
||||
|
||||
text += templates.TEMPLATE_CLASS_INDEX % (label, label)
|
||||
|
||||
text += 80*'=' + ' ' + 80*'=' + '\n'
|
||||
text += '%-80s **Short Description**\n'%'**Class**'
|
||||
@@ -391,8 +403,24 @@ def MakeClassIndex(file):
|
||||
for cls in names:
|
||||
text += '%-80s %s\n'%(':ref:`%s`'%Wx2Sphinx(cls)[1], classes[cls])
|
||||
|
||||
text += 80*'=' + ' ' + 80*'=' + '\n'
|
||||
text += 80*'=' + ' ' + 80*'=' + '\n\n'
|
||||
|
||||
contents = []
|
||||
for cls in names:
|
||||
contents.append(Wx2Sphinx(cls)[1])
|
||||
|
||||
for enum in enum_base:
|
||||
if enum.count('.') == enumDots:
|
||||
contents.append(enum)
|
||||
|
||||
contents.sort()
|
||||
|
||||
toctree = ''
|
||||
for item in contents:
|
||||
toctree += ' %s\n'%item
|
||||
|
||||
text += templates.TEMPLATE_TOCTREE%toctree
|
||||
|
||||
writeIfChanged(text_file, text)
|
||||
|
||||
|
||||
|
||||
@@ -16,9 +16,9 @@ TEMPLATE_DESCRIPTION = '''
|
||||
|
||||
.. _%s:
|
||||
|
||||
=====================================================================================
|
||||
==========================================================================================================================================
|
||||
|phoenix_title| **%s**
|
||||
=====================================================================================
|
||||
==========================================================================================================================================
|
||||
|
||||
'''
|
||||
|
||||
@@ -93,6 +93,18 @@ TEMPLATE_SUBCLASSES = '''
|
||||
|
||||
'''
|
||||
|
||||
# Template for the superclasses of a class, with a string containing a list
|
||||
# of comma separated class names with their ReST role as :ref: prepended
|
||||
TEMPLATE_SUPERCLASSES = '''
|
||||
|super_classes| Known Superclasses
|
||||
==================================
|
||||
|
||||
%s
|
||||
|
||||
|
|
||||
|
||||
'''
|
||||
|
||||
|
||||
# Template for the method summary of a class, containing a table made of
|
||||
# ``method_name`` ``method description``
|
||||
@@ -247,3 +259,53 @@ TEMPLATE_HEADINGS = '''
|
||||
|
||||
'''
|
||||
|
||||
# Templates for the summary of modules/packages, containing a table made of
|
||||
# ``module name`` ``short description``
|
||||
TEMPLATE_MODULE_SUMMARY = '''
|
||||
|module_summary| Modules Summary
|
||||
================================
|
||||
|
||||
%s
|
||||
|
||||
|
|
||||
|
||||
'''
|
||||
|
||||
TEMPLATE_PACKAGE_SUMMARY = '''
|
||||
|package_summary| Packages Summary
|
||||
==================================
|
||||
|
||||
%s
|
||||
|
||||
|
|
||||
|
||||
'''
|
||||
|
||||
TEMPLATE_STD_FUNCTION_SUMMARY = '''
|
||||
|function_summary| Functions Summary
|
||||
====================================
|
||||
|
||||
%s
|
||||
|
||||
|
|
||||
|
||||
'''
|
||||
|
||||
TEMPLATE_STD_CLASS_SUMMARY = '''
|
||||
|class_summary| Classes Summary
|
||||
===============================
|
||||
|
||||
%s
|
||||
|
||||
|
|
||||
|
||||
'''
|
||||
|
||||
|
||||
TEMPLATE_TOCTREE = '''
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:hidden:
|
||||
|
||||
%s
|
||||
'''
|
||||
|
||||
@@ -458,26 +458,38 @@ def FindControlImages(element):
|
||||
|
||||
# ----------------------------------------------------------------------- #
|
||||
|
||||
def MakeSummary(name, item_list, template, kind):
|
||||
def MakeSummary(item_list, template, kind, add_tilde=True):
|
||||
"""
|
||||
This function generates a table containing a method/property name
|
||||
and a shortened version of its docstrings.
|
||||
|
||||
:param string `name`: the method/property class name.
|
||||
:param list `item_list`: a list of tuples like `(method/property name, short docstrings)`.
|
||||
:param string `template`: the template to use (from `sphinxtools/templates.py`, can
|
||||
be the ``TEMPLATE_METHOD_SUMMARY`` or the ``TEMPLATE_PROPERTY_SUMMARY``.
|
||||
:param string `kind`: can be ":meth:" or ":attr:".
|
||||
:param string `kind`: can be ":meth:" or ":attr:" or ":ref:".
|
||||
|
||||
:rtype: `string`
|
||||
"""
|
||||
|
||||
maxlen = 0
|
||||
for method, simple_docs in item_list:
|
||||
substr = ':%s:`~%s`'%(kind, method)
|
||||
maxlen = max(maxlen, len(substr))
|
||||
|
||||
maxlen = max(80, maxlen)
|
||||
|
||||
summary = '='*80 + ' ' + '='*80 + "\n"
|
||||
summary = '='*maxlen + ' ' + '='*80 + "\n"
|
||||
format = '%-' + str(maxlen) + 's %s'
|
||||
|
||||
for method, simple_docs in item_list:
|
||||
summary += '%-80s %s'%(':%s:`~%s.%s`'%(kind, name, method), simple_docs) + '\n'
|
||||
if add_tilde:
|
||||
substr = ':%s:`~%s`'%(kind, method)
|
||||
else:
|
||||
substr = ':%s:`%s`'%(kind, method)
|
||||
|
||||
summary += format%(substr, simple_docs) + '\n'
|
||||
|
||||
summary += '='*80 + ' ' + '='*80 + "\n"
|
||||
summary += '='*maxlen + ' ' + '='*80 + "\n"
|
||||
|
||||
return template % summary
|
||||
|
||||
@@ -585,7 +597,7 @@ def PickleClassInfo(class_name, element):
|
||||
|
||||
for base in element.bases:
|
||||
bases.append(Wx2Sphinx(base)[1])
|
||||
|
||||
|
||||
items[class_name] = (method_list, bases)
|
||||
fid = open(pickle_file, 'wb')
|
||||
cPickle.dump(items, fid)
|
||||
|
||||
Reference in New Issue
Block a user