| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 |
- """ This script generates a pandadoc.hpp file representing the Python
- wrappers that can be parsed by doxygen to generate the Python documentation.
- You need to run this before invoking Doxyfile.python.
- It requires a valid makepanda installation with interrogatedb .in
- files in the lib/pandac/input directory. """
- __all__ = []
- import os
- import panda3d, pandac
- from panda3d.dtoolconfig import *
- LICENSE = """PANDA 3D SOFTWARE
- Copyright (c) Carnegie Mellon University. All rights reserved.
- All use of this software is subject to the terms of the revised BSD
- license. You should have received a copy of this license along
- with this source code in a file named \"LICENSE.\"""".split("\n")
- def comment(code):
- if not code:
- return ""
- comment = ''
- empty_line = False
- for line in code.splitlines(False):
- line = line.strip('\t\n /')
- if line:
- if empty_line:
- # New paragraph.
- comment += '\n\n'
- empty_line = False
- elif comment:
- comment += '\n'
- comment += '/// ' + line
- else:
- empty_line = True
- if comment:
- return comment
- else:
- return ''
- def block_comment(code):
- if not code:
- return ""
- lines = code.split("\n")
- newlines = []
- indent = 0
- reading_desc = False
- for line in lines:
- if line.startswith("////"):
- continue
- line = line.rstrip()
- strline = line.lstrip('/ \t')
- if ':' in strline:
- pre, post = strline.split(':', 1)
- pre = pre.rstrip()
- if pre == "Description":
- strline = post.lstrip()
- elif pre in ("Class", "Access", "Function", "Created by", "Enum"):
- continue
- if strline or len(newlines) > 0:
- newlines.append('/// ' + strline)
- #if reading_desc:
- # newlines.append('/// ' + line[min(indent, len(line) - len(strline)):])
- #else:
- # # A "Description:" text starts the description.
- # if strline.startswith("Description"):
- # strline = strline[11:].lstrip(': \t')
- # indent = len(line) - len(strline)
- # reading_desc = True
- # newlines.append('/// ' + strline)
- # else:
- # print line
- newcode = '\n'.join(newlines)
- if len(newcode) > 0:
- return newcode
- else:
- return ""
- def translateFunctionName(name):
- if name.startswith("__"):
- return name
- new = ""
- for i in name.split("_"):
- if new == "":
- new += i
- elif i == "":
- pass
- elif len(i) == 1:
- new += i[0].upper()
- else:
- new += i[0].upper() + i[1:]
- return new
- def translateTypeName(name, mangle=True):
- # Equivalent to C++ classNameFromCppName
- class_name = ""
- bad_chars = "!@#$%^&*()<>,.-=+~{}? "
- next_cap = False
- first_char = mangle
- for chr in name:
- if (chr == '_' or chr == ' ') and mangle:
- next_cap = True
- elif chr in bad_chars:
- if not mangle:
- class_name += '_'
- elif next_cap or first_char:
- class_name += chr.upper()
- next_cap = False
- first_char = False
- else:
- class_name += chr
- return class_name
- def translated_type_name(type, scoped=True):
- while interrogate_type_is_wrapped(type):
- if interrogate_type_is_const(type):
- return 'const ' + translated_type_name(interrogate_type_wrapped_type(type))
- else:
- type = interrogate_type_wrapped_type(type)
- typename = interrogate_type_name(type)
- if typename in ("PyObject", "_object"):
- return "object"
- elif typename == "PN_stdfloat":
- return "float"
- if interrogate_type_is_atomic(type):
- token = interrogate_type_atomic_token(type)
- if token == 7:
- return 'str'
- else:
- return typename
- if not typename.endswith('_t'):
- # Hack: don't mangle size_t etc.
- typename = translateTypeName(typename)
- if scoped and interrogate_type_is_nested(type):
- return translated_type_name(interrogate_type_outer_class(type)) + '::' + typename
- else:
- return typename
- def processElement(handle, element):
- if interrogate_element_has_comment(element):
- print >>handle, comment(interrogate_element_comment(element))
- print >>handle, translated_type_name(interrogate_element_type(element)),
- print >>handle, interrogate_element_name(element) + ';'
- def processFunction(handle, function, isConstructor = False):
- for i_wrapper in xrange(interrogate_function_number_of_python_wrappers(function)):
- wrapper = interrogate_function_python_wrapper(function, i_wrapper)
- if interrogate_wrapper_has_comment(wrapper):
- print >>handle, block_comment(interrogate_wrapper_comment(wrapper))
- if not isConstructor:
- if interrogate_function_is_method(function):
- if not interrogate_wrapper_number_of_parameters(wrapper) > 0 or not interrogate_wrapper_parameter_is_this(wrapper, 0):
- print >>handle, "static",
- if interrogate_wrapper_has_return_value(wrapper):
- print >>handle, translated_type_name(interrogate_wrapper_return_type(wrapper)),
- else:
- pass#print >>handle, "void",
- print >>handle, translateFunctionName(interrogate_function_name(function)) + "(",
- else:
- print >>handle, "__init__(",
- first = True
- for i_param in range(interrogate_wrapper_number_of_parameters(wrapper)):
- if not interrogate_wrapper_parameter_is_this(wrapper, i_param):
- if not first:
- print >>handle, ",",
- print >>handle, translated_type_name(interrogate_wrapper_parameter_type(wrapper, i_param)),
- if interrogate_wrapper_parameter_has_name(wrapper, i_param):
- print >>handle, interrogate_wrapper_parameter_name(wrapper, i_param),
- first = False
- print >>handle, ");"
- def processType(handle, type):
- typename = translated_type_name(type, scoped=False)
- derivations = [ translated_type_name(interrogate_type_get_derivation(type, n)) for n in range(interrogate_type_number_of_derivations(type)) ]
- if interrogate_type_has_comment(type):
- print >>handle, block_comment(interrogate_type_comment(type))
- if interrogate_type_is_enum(type):
- print >>handle, "enum %s {" % typename
- for i_value in range(interrogate_type_number_of_enum_values(type)):
- docstring = comment(interrogate_type_enum_value_comment(type, i_value))
- if docstring:
- print >>handle, docstring
- print >>handle, interrogate_type_enum_value_name(type, i_value), "=", interrogate_type_enum_value(type, i_value), ","
- elif interrogate_type_is_typedef(type):
- wrapped_type = translated_type_name(interrogate_type_wrapped_type(type))
- print >>handle, "typedef %s %s;" % (wrapped_type, typename)
- return
- else:
- if interrogate_type_is_struct(type):
- classtype = "struct"
- elif interrogate_type_is_class(type):
- classtype = "class"
- elif interrogate_type_is_union(type):
- classtype = "union"
- else:
- print "I don't know what type %s is" % interrogate_type_true_name(type)
- return
- if len(derivations) > 0:
- print >>handle, "%s %s : public %s {" % (classtype, typename, ", public ".join(derivations))
- else:
- print >>handle, "%s %s {" % (classtype, typename)
- print >>handle, "public:"
- for i_ntype in xrange(interrogate_type_number_of_nested_types(type)):
- processType(handle, interrogate_type_get_nested_type(type, i_ntype))
- for i_method in xrange(interrogate_type_number_of_constructors(type)):
- processFunction(handle, interrogate_type_get_constructor(type, i_method), True)
- for i_method in xrange(interrogate_type_number_of_methods(type)):
- processFunction(handle, interrogate_type_get_method(type, i_method))
- for i_method in xrange(interrogate_type_number_of_make_seqs(type)):
- print >>handle, "list", translateFunctionName(interrogate_make_seq_seq_name(interrogate_type_get_make_seq(type, i_method))), "();"
- for i_element in xrange(interrogate_type_number_of_elements(type)):
- processElement(handle, interrogate_type_get_element(type, i_element))
- print >>handle, "};"
- def processModule(handle, package):
- print >>handle, "namespace %s {" % package
- if package != "core":
- print >>handle, "using namespace core;"
- for i_type in xrange(interrogate_number_of_global_types()):
- type = interrogate_get_global_type(i_type)
- if interrogate_type_has_module_name(type):
- module_name = interrogate_type_module_name(type)
- if "panda3d." + package == module_name:
- processType(handle, type)
- else:
- print "Type %s has no module name" % typename
- for i_func in xrange(interrogate_number_of_global_functions()):
- func = interrogate_get_global_function(i_func)
- if interrogate_function_has_module_name(func):
- module_name = interrogate_function_module_name(func)
- if "panda3d." + package == module_name:
- processFunction(handle, func)
- else:
- print "Type %s has no module name" % typename
- print >>handle, "}"
- if __name__ == "__main__":
- handle = open("pandadoc.hpp", "w")
- print >>handle, comment("Panda3D modules that are implemented in C++.")
- print >>handle, "namespace panda3d {"
- # Determine the path to the interrogatedb files
- interrogate_add_search_directory(os.path.join(os.path.dirname(pandac.__file__), "..", "..", "etc"))
- interrogate_add_search_directory(os.path.join(os.path.dirname(pandac.__file__), "input"))
- import panda3d.core
- processModule(handle, "core")
- for lib in os.listdir(os.path.dirname(panda3d.__file__)):
- if lib.endswith(('.pyd', '.so')) and not lib.startswith('core.'):
- module_name = os.path.splitext(lib)[0]
- __import__("panda3d." + module_name)
- processModule(handle, module_name)
- print >>handle, "}"
- handle.close()
|