Adds target to build doxygen-python documentation, that take
pcbnew.py + doxygen-xml files, and build .i files with docstrings, those .i files are included back again to build a pcbnew.py with extended documentation from C++, finally we take the final pcbnew.py to build the doxygen-python documentation
This commit is contained in:
parent
4f78403463
commit
a602c1b2fe
|
@ -288,7 +288,14 @@ if( KICAD_SCRIPTING )
|
|||
|
||||
set( SWIG_OPTS -python -c++ -outdir ${CMAKE_CURRENT_BINARY_DIR} ${SWIG_FLAGS} )
|
||||
|
||||
if( EXISTS ${CMAKE_CURRENT_BINARY_DIR}/doxygen-xml )
|
||||
set( SWIG_OPTS ${SWIG_OPTS} -DENABLE_DOCSTRINGS_FROM_DOXYGEN )
|
||||
set( SWIG_OPTS ${SWIG_OPTS} -I${CMAKE_CURRENT_BINARY_DIR}/docstrings )
|
||||
endif()
|
||||
|
||||
add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/pcbnew_wrap.cxx
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/pcbnew.py
|
||||
|
||||
DEPENDS pcbcommon
|
||||
DEPENDS scripting/pcbnew.i
|
||||
DEPENDS scripting/board.i
|
||||
|
@ -301,6 +308,9 @@ if( KICAD_SCRIPTING )
|
|||
DEPENDS ../scripting/wx.i
|
||||
DEPENDS ../scripting/kicadplugins.i
|
||||
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/docstrings
|
||||
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/docstrings/docstrings.i # this makes docstrings.i available if it doesn't exist
|
||||
|
||||
COMMAND ${SWIG_EXECUTABLE} ${SWIG_OPTS} -o ${CMAKE_CURRENT_BINARY_DIR}/pcbnew_wrap.cxx scripting/pcbnew.i
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/../scripting/fixswigimports.py ${CMAKE_CURRENT_BINARY_DIR}/pcbnew.py
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
|
@ -340,6 +350,56 @@ if( KICAD_SCRIPTING_MODULES )
|
|||
|
||||
endif()
|
||||
|
||||
|
||||
###
|
||||
# Doxygen python documentation
|
||||
###
|
||||
|
||||
find_package( Doxygen )
|
||||
if( DOXYGEN_FOUND )
|
||||
if( KICAD_SCRIPTING )
|
||||
|
||||
# create XML files from doxygen parsing
|
||||
add_custom_target( doxygen-python-xml
|
||||
${CMAKE_COMMAND} -E remove_directory doxygen-python-xml
|
||||
COMMAND SOURCES_DIR=${CMAKE_SOURCE_DIR} ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile_xml
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
DEPENDS Doxyfile_xml
|
||||
COMMENT "building doxygen docs into directory doxygen-python/html"
|
||||
)
|
||||
|
||||
# create .i files from XML doxygen parsing, docstrings.i will include all of them
|
||||
add_custom_target( xml-to-docstrings
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory docstrings
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory docstrings
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripting/extract-docstrings.py pcbnew.py doxygen-xml/xml docstrings
|
||||
|
||||
COMMAND ${CMAKE_COMMAND} -E remove pcbnew.py # force removal so it will be recreated later
|
||||
COMMENT "building docstring files"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
DEPENDS pcbnew.py
|
||||
DEPENDS doxygen-python-xml
|
||||
)
|
||||
|
||||
# create doxygen-python html
|
||||
add_custom_target( doxygen-python
|
||||
${CMAKE_COMMAND} -E remove_directory doxygen-python
|
||||
COMMAND PYTHON_SOURCES_TO_DOC=${CMAKE_CURRENT_BINARY_DIR}/pcbnew.py ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile_python
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
DEPENDS Doxyfile.python
|
||||
DEPENDS xml-to-docstrings
|
||||
DEPENDS pcbnew.py
|
||||
|
||||
COMMENT "building doxygen docs into directory doxygen-python/html"
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
message( STATUS "WARNING: Doxygen not found - doxygen-docs (Source Docs) target not created" )
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
|
||||
###
|
||||
# Windows resource file
|
||||
###
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,315 @@
|
|||
# Doxyfile 1.8.5
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = "KiCad PCB EDA Suite"
|
||||
PROJECT_NUMBER =
|
||||
PROJECT_BRIEF =
|
||||
PROJECT_LOGO =
|
||||
OUTPUT_DIRECTORY = doxygen-xml
|
||||
CREATE_SUBDIRS = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ABBREVIATE_BRIEF =
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
INLINE_INHERITED_MEMB = YES
|
||||
FULL_PATH_NAMES = NO
|
||||
STRIP_FROM_PATH =
|
||||
STRIP_FROM_INC_PATH =
|
||||
SHORT_NAMES = NO
|
||||
JAVADOC_AUTOBRIEF = YES
|
||||
QT_AUTOBRIEF = NO
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
INHERIT_DOCS = YES
|
||||
SEPARATE_MEMBER_PAGES = NO
|
||||
TAB_SIZE = 4
|
||||
ALIASES =
|
||||
TCL_SUBST =
|
||||
OPTIMIZE_OUTPUT_FOR_C = NO
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
OPTIMIZE_FOR_FORTRAN = NO
|
||||
OPTIMIZE_OUTPUT_VHDL = NO
|
||||
EXTENSION_MAPPING =
|
||||
MARKDOWN_SUPPORT = YES
|
||||
AUTOLINK_SUPPORT = YES
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
CPP_CLI_SUPPORT = NO
|
||||
SIP_SUPPORT = NO
|
||||
IDL_PROPERTY_SUPPORT = YES
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
SUBGROUPING = YES
|
||||
INLINE_GROUPED_CLASSES = NO
|
||||
INLINE_SIMPLE_STRUCTS = NO
|
||||
TYPEDEF_HIDES_STRUCT = NO
|
||||
LOOKUP_CACHE_SIZE = 0
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
EXTRACT_ALL = YES
|
||||
EXTRACT_PRIVATE = YES
|
||||
EXTRACT_PACKAGE = NO
|
||||
EXTRACT_STATIC = YES
|
||||
EXTRACT_LOCAL_CLASSES = YES
|
||||
EXTRACT_LOCAL_METHODS = NO
|
||||
EXTRACT_ANON_NSPACES = NO
|
||||
HIDE_UNDOC_MEMBERS = NO
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
HIDE_FRIEND_COMPOUNDS = NO
|
||||
HIDE_IN_BODY_DOCS = NO
|
||||
INTERNAL_DOCS = NO
|
||||
CASE_SENSE_NAMES = YES
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
FORCE_LOCAL_INCLUDES = NO
|
||||
INLINE_INFO = YES
|
||||
SORT_MEMBER_DOCS = YES
|
||||
SORT_BRIEF_DOCS = NO
|
||||
SORT_MEMBERS_CTORS_1ST = NO
|
||||
SORT_GROUP_NAMES = NO
|
||||
SORT_BY_SCOPE_NAME = NO
|
||||
STRICT_PROTO_MATCHING = NO
|
||||
GENERATE_TODOLIST = YES
|
||||
GENERATE_TESTLIST = YES
|
||||
GENERATE_BUGLIST = YES
|
||||
GENERATE_DEPRECATEDLIST= YES
|
||||
ENABLED_SECTIONS =
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
SHOW_USED_FILES = YES
|
||||
SHOW_FILES = YES
|
||||
SHOW_NAMESPACES = YES
|
||||
FILE_VERSION_FILTER =
|
||||
LAYOUT_FILE =
|
||||
CITE_BIB_FILES =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to warning and progress messages
|
||||
#---------------------------------------------------------------------------
|
||||
QUIET = NO
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
WARN_NO_PARAMDOC = NO
|
||||
WARN_FORMAT = "$file:$line: $text "
|
||||
WARN_LOGFILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = $(SOURCES_DIR)/kicad \
|
||||
$(SOURCES_DIR)/pcbnew \
|
||||
$(SOURCES_DIR)/3d-viewer \
|
||||
$(SOURCES_DIR)/common \
|
||||
$(SOURCES_DIR)/include \
|
||||
$(SOURCES_DIR)/polygon \
|
||||
$(SOURCES_DIR)/potrace
|
||||
INPUT_ENCODING = UTF-8
|
||||
FILE_PATTERNS = *.h \
|
||||
*.cpp
|
||||
RECURSIVE = YES
|
||||
EXCLUDE = $(SOURCES_DIR)/include/boost
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXCLUDE_PATTERNS =
|
||||
EXCLUDE_SYMBOLS =
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS =
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
IMAGE_PATH =
|
||||
INPUT_FILTER =
|
||||
FILTER_PATTERNS =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
FILTER_SOURCE_PATTERNS =
|
||||
USE_MDFILE_AS_MAINPAGE =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to source browsing
|
||||
#---------------------------------------------------------------------------
|
||||
SOURCE_BROWSER = YES
|
||||
INLINE_SOURCES = YES
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
REFERENCED_BY_RELATION = YES
|
||||
REFERENCES_RELATION = YES
|
||||
REFERENCES_LINK_SOURCE = YES
|
||||
SOURCE_TOOLTIPS = YES
|
||||
USE_HTAGS = NO
|
||||
VERBATIM_HEADERS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
ALPHABETICAL_INDEX = YES
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
IGNORE_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_HTML = NO
|
||||
HTML_OUTPUT = html
|
||||
HTML_FILE_EXTENSION = .html
|
||||
HTML_HEADER =
|
||||
HTML_FOOTER =
|
||||
HTML_STYLESHEET =
|
||||
HTML_EXTRA_STYLESHEET =
|
||||
HTML_EXTRA_FILES =
|
||||
HTML_COLORSTYLE_HUE = 220
|
||||
HTML_COLORSTYLE_SAT = 100
|
||||
HTML_COLORSTYLE_GAMMA = 80
|
||||
HTML_TIMESTAMP = YES
|
||||
HTML_DYNAMIC_SECTIONS = NO
|
||||
HTML_INDEX_NUM_ENTRIES = 100
|
||||
GENERATE_DOCSET = NO
|
||||
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||
DOCSET_BUNDLE_ID = org.doxygen.Project
|
||||
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
|
||||
DOCSET_PUBLISHER_NAME = Publisher
|
||||
GENERATE_HTMLHELP = NO
|
||||
CHM_FILE =
|
||||
HHC_LOCATION =
|
||||
GENERATE_CHI = NO
|
||||
CHM_INDEX_ENCODING =
|
||||
BINARY_TOC = NO
|
||||
TOC_EXPAND = NO
|
||||
GENERATE_QHP = NO
|
||||
QCH_FILE =
|
||||
QHP_NAMESPACE = org.doxygen.Project
|
||||
QHP_VIRTUAL_FOLDER = doc
|
||||
QHP_CUST_FILTER_NAME =
|
||||
QHP_CUST_FILTER_ATTRS =
|
||||
QHP_SECT_FILTER_ATTRS =
|
||||
QHG_LOCATION =
|
||||
GENERATE_ECLIPSEHELP = NO
|
||||
ECLIPSE_DOC_ID = org.doxygen.Project
|
||||
DISABLE_INDEX = NO
|
||||
GENERATE_TREEVIEW = YES
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
TREEVIEW_WIDTH = 250
|
||||
EXT_LINKS_IN_WINDOW = NO
|
||||
FORMULA_FONTSIZE = 10
|
||||
FORMULA_TRANSPARENT = YES
|
||||
USE_MATHJAX = NO
|
||||
MATHJAX_FORMAT = HTML-CSS
|
||||
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
|
||||
MATHJAX_EXTENSIONS =
|
||||
MATHJAX_CODEFILE =
|
||||
SEARCHENGINE = NO
|
||||
SERVER_BASED_SEARCH = NO
|
||||
EXTERNAL_SEARCH = NO
|
||||
SEARCHENGINE_URL =
|
||||
SEARCHDATA_FILE = searchdata.xml
|
||||
EXTERNAL_SEARCH_ID =
|
||||
EXTRA_SEARCH_MAPPINGS =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the LaTeX output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_LATEX = NO
|
||||
LATEX_OUTPUT = latex
|
||||
LATEX_CMD_NAME = latex
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
COMPACT_LATEX = NO
|
||||
PAPER_TYPE = a4wide
|
||||
EXTRA_PACKAGES =
|
||||
LATEX_HEADER =
|
||||
LATEX_FOOTER =
|
||||
LATEX_EXTRA_FILES =
|
||||
PDF_HYPERLINKS = NO
|
||||
USE_PDFLATEX = NO
|
||||
LATEX_BATCHMODE = NO
|
||||
LATEX_HIDE_INDICES = NO
|
||||
LATEX_SOURCE_CODE = NO
|
||||
LATEX_BIB_STYLE = plain
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the RTF output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_RTF = NO
|
||||
RTF_OUTPUT = rtf
|
||||
COMPACT_RTF = NO
|
||||
RTF_HYPERLINKS = NO
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_MAN = NO
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
MAN_LINKS = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the XML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_XML = YES
|
||||
XML_OUTPUT = xml
|
||||
XML_SCHEMA =
|
||||
XML_DTD =
|
||||
XML_PROGRAMLISTING = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the DOCBOOK output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_DOCBOOK = NO
|
||||
DOCBOOK_OUTPUT = docbook
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the Perl module output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_PERLMOD = NO
|
||||
PERLMOD_LATEX = NO
|
||||
PERLMOD_PRETTY = YES
|
||||
PERLMOD_MAKEVAR_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = NO
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH = $(SOURCES_DIR)/include \
|
||||
$(SOURCES_DIR)/pcbnew \
|
||||
$(SOURCES_DIR)/eeschema \
|
||||
$(SOURCES_DIR)/gerbview
|
||||
INCLUDE_FILE_PATTERNS = *.h
|
||||
PREDEFINED =
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE =
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
EXTERNAL_PAGES = YES
|
||||
PERL_PATH = /usr/bin/perl
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
CLASS_DIAGRAMS = YES
|
||||
MSCGEN_PATH =
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
HAVE_DOT = NO
|
||||
DOT_NUM_THREADS = 0
|
||||
DOT_FONTNAME = Helvetica
|
||||
DOT_FONTSIZE = 10
|
||||
DOT_FONTPATH =
|
||||
CLASS_GRAPH = YES
|
||||
COLLABORATION_GRAPH = YES
|
||||
GROUP_GRAPHS = YES
|
||||
UML_LOOK = NO
|
||||
UML_LIMIT_NUM_FIELDS = 10
|
||||
TEMPLATE_RELATIONS = YES
|
||||
INCLUDE_GRAPH = YES
|
||||
INCLUDED_BY_GRAPH = YES
|
||||
CALL_GRAPH = NO
|
||||
CALLER_GRAPH = NO
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
DIRECTORY_GRAPH = YES
|
||||
DOT_IMAGE_FORMAT = png
|
||||
INTERACTIVE_SVG = NO
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
MSCFILE_DIRS =
|
||||
DOT_GRAPH_MAX_NODES = 50
|
||||
MAX_DOT_GRAPH_DEPTH = 0
|
||||
DOT_TRANSPARENT = NO
|
||||
DOT_MULTI_TARGETS = NO
|
||||
GENERATE_LEGEND = YES
|
||||
DOT_CLEANUP = YES
|
|
@ -31,6 +31,9 @@
|
|||
%module pcbnew
|
||||
|
||||
%feature("autodoc", "1");
|
||||
#ifdef ENABLE_DOCSTRINGS_FROM_DOXYGEN
|
||||
%include "docstrings.i"
|
||||
#endif
|
||||
|
||||
%include "kicad.i"
|
||||
|
||||
|
|
|
@ -0,0 +1,405 @@
|
|||
#!/usr/bin/env python
|
||||
"""Doxygen XML to SWIG docstring converter.
|
||||
|
||||
Converts Doxygen generated XML files into a file containing docstrings
|
||||
that can be used by SWIG >1.3.23
|
||||
|
||||
Usage:
|
||||
|
||||
extract-docstrings.py input_py_wrapper.py input_xml_dir output_directory
|
||||
|
||||
input_py_wrapper.py is a swig generated file, with/without docstrings,
|
||||
so we can get to know which classes are inspected by swig
|
||||
|
||||
input_xml_dir is your doxygen generated XML directory
|
||||
|
||||
output_directory is the directory where output will be written
|
||||
|
||||
"""
|
||||
|
||||
# This code is implemented using Mark Pilgrim's code as a guideline:
|
||||
# http://www.faqs.org/docs/diveintopython/kgp_divein.html
|
||||
# Based in doxy2swig.py
|
||||
# Author: Prabhu Ramachandran
|
||||
# License: BSD style
|
||||
|
||||
|
||||
from xml.dom import minidom
|
||||
import re
|
||||
import textwrap
|
||||
import sys
|
||||
import types
|
||||
import os.path
|
||||
|
||||
|
||||
def my_open_read(source):
|
||||
if hasattr(source, "read"):
|
||||
return source
|
||||
else:
|
||||
return open(source)
|
||||
|
||||
def my_open_write(dest):
|
||||
if hasattr(dest, "write"):
|
||||
return dest
|
||||
else:
|
||||
return open(dest, 'w')
|
||||
|
||||
|
||||
class Doxy2SWIG:
|
||||
"""Converts Doxygen generated XML files into a file containing
|
||||
docstrings that can be used by SWIG-1.3.x that have support for
|
||||
feature("docstring"). Once the data is parsed it is stored in
|
||||
self.pieces.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, src):
|
||||
"""Initialize the instance given a source object (file or
|
||||
filename).
|
||||
|
||||
"""
|
||||
f = my_open_read(src)
|
||||
self.my_dir = os.path.dirname(f.name)
|
||||
self.xmldoc = minidom.parse(f).documentElement
|
||||
f.close()
|
||||
|
||||
self.pieces = []
|
||||
self.pieces.append('\n// File: %s\n'%\
|
||||
os.path.basename(f.name))
|
||||
|
||||
self.space_re = re.compile(r'\s+')
|
||||
self.lead_spc = re.compile(r'^(%feature\S+\s+\S+\s*?)"\s+(\S)')
|
||||
self.multi = 0
|
||||
self.ignores = ('inheritancegraph', 'param', 'listofallmembers',
|
||||
'innerclass', 'name', 'declname', 'incdepgraph',
|
||||
'invincdepgraph', 'programlisting', 'type',
|
||||
'references', 'referencedby', 'location',
|
||||
'collaborationgraph', 'reimplements',
|
||||
'reimplementedby', 'derivedcompoundref',
|
||||
'basecompoundref')
|
||||
#self.generics = []
|
||||
|
||||
def generate(self):
|
||||
"""Parses the file set in the initialization. The resulting
|
||||
data is stored in `self.pieces`.
|
||||
|
||||
"""
|
||||
self.parse(self.xmldoc)
|
||||
|
||||
def parse(self, node):
|
||||
"""Parse a given node. This function in turn calls the
|
||||
`parse_<nodeType>` functions which handle the respective
|
||||
nodes.
|
||||
|
||||
"""
|
||||
pm = getattr(self, "parse_%s"%node.__class__.__name__)
|
||||
pm(node)
|
||||
|
||||
def parse_Document(self, node):
|
||||
self.parse(node.documentElement)
|
||||
|
||||
def parse_Text(self, node):
|
||||
txt = node.data
|
||||
txt = txt.replace('\\', r'\\\\')
|
||||
txt = txt.replace('"', r'\"')
|
||||
# ignore pure whitespace
|
||||
m = self.space_re.match(txt)
|
||||
if m and len(m.group()) == len(txt):
|
||||
pass
|
||||
else:
|
||||
self.add_text(textwrap.fill(txt))
|
||||
|
||||
def parse_Element(self, node):
|
||||
"""Parse an `ELEMENT_NODE`. This calls specific
|
||||
`do_<tagName>` handers for different elements. If no handler
|
||||
is available the `generic_parse` method is called. All
|
||||
tagNames specified in `self.ignores` are simply ignored.
|
||||
|
||||
"""
|
||||
name = node.tagName
|
||||
ignores = self.ignores
|
||||
if name in ignores:
|
||||
return
|
||||
attr = "do_%s" % name
|
||||
if hasattr(self, attr):
|
||||
handlerMethod = getattr(self, attr)
|
||||
handlerMethod(node)
|
||||
else:
|
||||
self.generic_parse(node)
|
||||
#if name not in self.generics: self.generics.append(name)
|
||||
|
||||
def add_text(self, value):
|
||||
"""Adds text corresponding to `value` into `self.pieces`."""
|
||||
if type(value) in (types.ListType, types.TupleType):
|
||||
self.pieces.extend(value)
|
||||
else:
|
||||
self.pieces.append(value)
|
||||
|
||||
def get_specific_nodes(self, node, names):
|
||||
"""Given a node and a sequence of strings in `names`, return a
|
||||
dictionary containing the names as keys and child
|
||||
`ELEMENT_NODEs`, that have a `tagName` equal to the name.
|
||||
|
||||
"""
|
||||
nodes = [(x.tagName, x) for x in node.childNodes \
|
||||
if x.nodeType == x.ELEMENT_NODE and \
|
||||
x.tagName in names]
|
||||
return dict(nodes)
|
||||
|
||||
def generic_parse(self, node, pad=0):
|
||||
"""A Generic parser for arbitrary tags in a node.
|
||||
|
||||
Parameters:
|
||||
|
||||
- node: A node in the DOM.
|
||||
- pad: `int` (default: 0)
|
||||
|
||||
If 0 the node data is not padded with newlines. If 1 it
|
||||
appends a newline after parsing the childNodes. If 2 it
|
||||
pads before and after the nodes are processed. Defaults to
|
||||
0.
|
||||
|
||||
"""
|
||||
npiece = 0
|
||||
if pad:
|
||||
npiece = len(self.pieces)
|
||||
if pad == 2:
|
||||
self.add_text('\n')
|
||||
for n in node.childNodes:
|
||||
self.parse(n)
|
||||
if pad:
|
||||
if len(self.pieces) > npiece:
|
||||
self.add_text('\n')
|
||||
|
||||
def space_parse(self, node):
|
||||
self.add_text(' ')
|
||||
self.generic_parse(node)
|
||||
|
||||
do_ref = space_parse
|
||||
do_emphasis = space_parse
|
||||
do_bold = space_parse
|
||||
do_computeroutput = space_parse
|
||||
do_formula = space_parse
|
||||
|
||||
def do_compoundname(self, node):
|
||||
self.add_text('\n\n')
|
||||
data = node.firstChild.data
|
||||
self.add_text('%%feature("docstring") %s "\n'%data)
|
||||
|
||||
def do_compounddef(self, node):
|
||||
kind = node.attributes['kind'].value
|
||||
if kind in ('class', 'struct'):
|
||||
prot = node.attributes['prot'].value
|
||||
if prot <> 'public':
|
||||
return
|
||||
names = ('compoundname', 'briefdescription',
|
||||
'detaileddescription', 'includes')
|
||||
first = self.get_specific_nodes(node, names)
|
||||
for n in names:
|
||||
if first.has_key(n):
|
||||
self.parse(first[n])
|
||||
self.add_text(['";','\n'])
|
||||
for n in node.childNodes:
|
||||
if n not in first.values():
|
||||
self.parse(n)
|
||||
elif kind in ('file', 'namespace'):
|
||||
nodes = node.getElementsByTagName('sectiondef')
|
||||
for n in nodes:
|
||||
self.parse(n)
|
||||
|
||||
def do_includes(self, node):
|
||||
self.add_text('C++ includes: ')
|
||||
self.generic_parse(node, pad=1)
|
||||
|
||||
def do_parameterlist(self, node):
|
||||
self.add_text(['\n', '\n', 'Parameters:', '\n'])
|
||||
self.generic_parse(node, pad=1)
|
||||
|
||||
def do_para(self, node):
|
||||
self.add_text('\n')
|
||||
self.generic_parse(node, pad=1)
|
||||
|
||||
def do_parametername(self, node):
|
||||
self.add_text('\n')
|
||||
try:
|
||||
self.add_text("%s: "%node.firstChild.data)
|
||||
except AttributeError:
|
||||
self.add_text("???: ")
|
||||
|
||||
def do_parameterdefinition(self, node):
|
||||
self.generic_parse(node, pad=1)
|
||||
|
||||
def do_detaileddescription(self, node):
|
||||
self.generic_parse(node, pad=1)
|
||||
|
||||
def do_briefdescription(self, node):
|
||||
self.generic_parse(node, pad=1)
|
||||
|
||||
def do_memberdef(self, node):
|
||||
prot = node.attributes['prot'].value
|
||||
id = node.attributes['id'].value
|
||||
kind = node.attributes['kind'].value
|
||||
tmp = node.parentNode.parentNode.parentNode
|
||||
compdef = tmp.getElementsByTagName('compounddef')[0]
|
||||
cdef_kind = compdef.attributes['kind'].value
|
||||
|
||||
if prot == 'public':
|
||||
first = self.get_specific_nodes(node, ('definition', 'name'))
|
||||
name = first['name'].firstChild.data
|
||||
if name[:8] == 'operator': # Don't handle operators yet.
|
||||
return
|
||||
|
||||
defn = first['definition'].firstChild.data
|
||||
self.add_text('\n')
|
||||
self.add_text('%feature("docstring") ')
|
||||
|
||||
anc = node.parentNode.parentNode
|
||||
if cdef_kind in ('file', 'namespace'):
|
||||
ns_node = anc.getElementsByTagName('innernamespace')
|
||||
if not ns_node and cdef_kind == 'namespace':
|
||||
ns_node = anc.getElementsByTagName('compoundname')
|
||||
if ns_node:
|
||||
ns = ns_node[0].firstChild.data
|
||||
self.add_text(' %s::%s "\n%s'%(ns, name, defn))
|
||||
else:
|
||||
self.add_text(' %s "\n%s'%(name, defn))
|
||||
elif cdef_kind in ('class', 'struct'):
|
||||
# Get the full function name.
|
||||
anc_node = anc.getElementsByTagName('compoundname')
|
||||
cname = anc_node[0].firstChild.data
|
||||
self.add_text(' %s::%s "\n%s'%(cname, name, defn))
|
||||
|
||||
|
||||
for n in node.childNodes:
|
||||
if n not in first.values():
|
||||
self.parse(n)
|
||||
self.add_text(['";', '\n'])
|
||||
|
||||
def do_definition(self, node):
|
||||
data = node.firstChild.data
|
||||
self.add_text('%s "\n%s'%(data, data))
|
||||
|
||||
def do_sectiondef(self, node):
|
||||
kind = node.attributes['kind'].value
|
||||
if kind in ('public-func', 'func'):
|
||||
self.generic_parse(node)
|
||||
|
||||
def do_simplesect(self, node):
|
||||
kind = node.attributes['kind'].value
|
||||
if kind in ('date', 'rcs', 'version'):
|
||||
pass
|
||||
elif kind == 'warning':
|
||||
self.add_text(['\n', 'WARNING: '])
|
||||
self.generic_parse(node)
|
||||
elif kind == 'see':
|
||||
self.add_text('\n')
|
||||
self.add_text('See: ')
|
||||
self.generic_parse(node)
|
||||
else:
|
||||
self.generic_parse(node)
|
||||
|
||||
def do_argsstring(self, node):
|
||||
self.generic_parse(node, pad=1)
|
||||
|
||||
def do_member(self, node):
|
||||
kind = node.attributes['kind'].value
|
||||
refid = node.attributes['refid'].value
|
||||
if kind == 'function' and refid[:9] == 'namespace':
|
||||
self.generic_parse(node)
|
||||
|
||||
def do_doxygenindex(self, node):
|
||||
self.multi = 1
|
||||
comps = node.getElementsByTagName('compound')
|
||||
for c in comps:
|
||||
refid = c.attributes['refid'].value
|
||||
fname = refid + '.xml'
|
||||
if not os.path.exists(fname):
|
||||
fname = os.path.join(self.my_dir, fname)
|
||||
print "parsing file: %s"%fname
|
||||
p = Doxy2SWIG(fname)
|
||||
p.generate()
|
||||
self.pieces.extend(self.clean_pieces(p.pieces))
|
||||
|
||||
def write(self, fname):
|
||||
o = my_open_write(fname)
|
||||
if self.multi:
|
||||
o.write("".join(self.pieces))
|
||||
else:
|
||||
o.write("".join(self.clean_pieces(self.pieces)))
|
||||
o.close()
|
||||
|
||||
def clean_pieces(self, pieces):
|
||||
"""Cleans the list of strings given as `pieces`. It replaces
|
||||
multiple newlines by a maximum of 2 and returns a new list.
|
||||
It also wraps the paragraphs nicely.
|
||||
|
||||
"""
|
||||
ret = []
|
||||
count = 0
|
||||
for i in pieces:
|
||||
if i == '\n':
|
||||
count = count + 1
|
||||
else:
|
||||
if i == '";':
|
||||
if count:
|
||||
ret.append('\n')
|
||||
elif count > 2:
|
||||
ret.append('\n\n')
|
||||
elif count:
|
||||
ret.append('\n'*count)
|
||||
count = 0
|
||||
ret.append(i)
|
||||
|
||||
_data = "".join(ret)
|
||||
ret = []
|
||||
for i in _data.split('\n\n'):
|
||||
if i == 'Parameters:':
|
||||
ret.extend(['Parameters:\n-----------', '\n\n'])
|
||||
elif i.find('// File:') > -1: # leave comments alone.
|
||||
ret.extend([i, '\n'])
|
||||
else:
|
||||
_tmp = textwrap.fill(i.strip())
|
||||
_tmp = self.lead_spc.sub(r'\1"\2', _tmp)
|
||||
ret.extend([_tmp, '\n\n'])
|
||||
return ret
|
||||
|
||||
|
||||
def get_python_classes(input_py):
|
||||
with open(input_py) as f:
|
||||
data = f.read()
|
||||
classes_supers = re.findall(r'class[ ]+([\w_]+)(\([\w_, ]+\))?:',data)
|
||||
classes = (classname for classname,superclass in classes_supers)
|
||||
return classes
|
||||
return []
|
||||
|
||||
def main(input_py, input_xml, output_dir):
|
||||
|
||||
classes = get_python_classes(input_py)
|
||||
|
||||
with file("%s/docstrings.i"%output_dir,'w') as f_index:
|
||||
|
||||
for classname in classes:
|
||||
|
||||
|
||||
class_file = "%s/class%s.xml"%(input_xml,classname.replace("_","__"))
|
||||
swig_file = "%s/%s.i"%(output_dir,classname.lower())
|
||||
|
||||
if os.path.isfile(class_file):
|
||||
print "processing:",class_file," ->",swig_file
|
||||
p = Doxy2SWIG(class_file)
|
||||
p.generate()
|
||||
p.write(swig_file)
|
||||
f_index.write('%%include "%s.i"\n'% classname.lower())
|
||||
#else:
|
||||
# print "ignoring class %s, as %s does not exist" %(classname,class_file)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print sys.argv
|
||||
if len(sys.argv) != 4:
|
||||
print __doc__
|
||||
sys.exit(1)
|
||||
main(sys.argv[1], sys.argv[2],sys.argv[3])
|
Loading…
Reference in New Issue