2009-12-25 16:50:53 +01:00
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
2010-02-12 14:34:04 +01:00
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
2009-12-25 16:50:53 +01:00
#
# Contributor(s): Campbell Barton
#
# #**** END GPL LICENSE BLOCK #****
2011-02-04 10:27:25 +01:00
# <pep8 compliant>
2009-12-25 16:50:53 +01:00
script_help_msg = '''
2010-10-13 12:42:33 +02:00
Usage :
2009-12-25 16:50:53 +01:00
2010-10-13 12:42:33 +02:00
For HTML generation
- - - - - - - - - - - - - - - - - - -
- Run this script from blenders root path once you have compiled blender
. / blender . bin - b - P doc / python_api / sphinx_doc_gen . py
2010-01-28 11:48:17 +01:00
2010-10-13 12:42:33 +02:00
This will generate python files in doc / python_api / sphinx - in / ,
assuming that . / blender . bin is or links to the blender executable
2010-01-28 11:48:17 +01:00
2010-10-13 12:42:33 +02:00
- Generate html docs by running . . .
2011-02-04 10:27:25 +01:00
2010-10-13 12:42:33 +02:00
sphinx - build doc / python_api / sphinx - in doc / python_api / sphinx - out
2011-03-22 05:28:51 +01:00
assuming that you have sphinx 1.0 .7 installed
2011-02-04 10:27:25 +01:00
2010-01-28 11:48:17 +01:00
For PDF generation
2010-10-13 12:42:33 +02:00
- - - - - - - - - - - - - - - - - -
- After you have built doc / python_api / sphinx - in ( see above ) , run :
2010-01-28 11:48:17 +01:00
2010-10-13 12:42:33 +02:00
sphinx - build - b latex doc / python_api / sphinx - in doc / python_api / sphinx - out
cd doc / python_api / sphinx - out
2010-01-28 11:48:17 +01:00
make
2009-12-25 16:50:53 +01:00
'''
2011-02-16 06:18:10 +01:00
# Switch for quick testing
if 1 :
# full build
EXCLUDE_MODULES = ( )
FILTER_BPY_TYPES = None
FILTER_BPY_OPS = None
else :
# for testing so doc-builds dont take so long.
EXCLUDE_MODULES = (
# "bpy.context",
" bpy.app " ,
" bpy.path " ,
" bpy.data " ,
2011-03-22 05:28:51 +01:00
" bpy.props " ,
2011-02-16 06:18:10 +01:00
" bpy.utils " ,
2011-02-18 09:47:37 +01:00
" bpy.context " ,
# "bpy.types", # supports filtering
2011-02-16 06:18:10 +01:00
" bpy.ops " , # supports filtering
" bge " ,
" aud " ,
" bgl " ,
" blf " ,
" mathutils " ,
" mathutils.geometry " ,
)
2011-02-18 15:27:18 +01:00
FILTER_BPY_TYPES = ( " PropertyGroup " , " Panel " , " Menu " , " Operator " , " RenderEngine " ) # allow
2011-02-18 09:47:37 +01:00
FILTER_BPY_OPS = ( " import.scene " , ) # allow
2011-02-16 06:18:10 +01:00
# for quick rebuilds
"""
rm - rf / b / doc / python_api / sphinx - * & & \
. / blender . bin - - background - - factory - startup - - python doc / python_api / sphinx_doc_gen . py & & \
sphinx - build doc / python_api / sphinx - in doc / python_api / sphinx - out
"""
2010-05-30 02:24:32 +02:00
# import rpdb2; rpdb2.start_embedded_debugger('test')
Mathutils refactor & include in sphinx generated docs, (TODO, include getset'ers in docs)
- Mathutils.MidpointVecs --> vector.lerp(other, fac)
- Mathutils.AngleBetweenVecs --> vector.angle(other)
- Mathutils.ProjectVecs --> vector.project(other)
- Mathutils.DifferenceQuats --> quat.difference(other)
- Mathutils.Slerp --> quat.slerp(other, fac)
- Mathutils.Rand: removed, use pythons random module
- Mathutils.RotationMatrix(angle, size, axis_flag, axis) --> Mathutils.RotationMatrix(angle, size, axis); merge axis & axis_flag args
- Matrix.scalePart --> Matrix.scale_part
- Matrix.translationPart --> Matrix.translation_part
- Matrix.rotationPart --> Matrix.rotation_part
- toMatrix --> to_matrix
- toEuler --> to_euler
- toQuat --> to_quat
- Vector.toTrackQuat --> Vector.to_track_quat
2010-01-25 10:44:04 +01:00
2009-12-25 16:50:53 +01:00
import os
2009-12-26 17:47:25 +01:00
import inspect
2009-12-25 16:50:53 +01:00
import bpy
import rna_info
2010-04-06 00:37:09 +02:00
# lame, python wont give some access
2010-08-11 19:13:39 +02:00
ClassMethodDescriptorType = type ( dict . __dict__ [ ' fromkeys ' ] )
2010-04-06 00:37:09 +02:00
MethodDescriptorType = type ( dict . get )
GetSetDescriptorType = type ( int . real )
2010-02-28 14:45:08 +01:00
EXAMPLE_SET = set ( )
EXAMPLE_SET_USED = set ( )
2010-04-10 20:35:50 +02:00
_BPY_STRUCT_FAKE = " bpy_struct "
2011-03-22 05:28:51 +01:00
_BPY_PROP_COLLECTION_FAKE = " bpy_prop_collection "
2010-05-03 17:52:15 +02:00
_BPY_FULL_REBUILD = False
2010-04-10 20:35:50 +02:00
2011-03-22 05:28:51 +01:00
if _BPY_PROP_COLLECTION_FAKE :
_BPY_PROP_COLLECTION_ID = " :class:` %s ` " % _BPY_PROP_COLLECTION_FAKE
else :
_BPY_PROP_COLLECTION_ID = " collection "
2010-12-10 01:20:32 +01:00
2011-03-27 07:23:14 +02:00
2010-06-15 04:06:01 +02:00
def undocumented_message ( module_name , type_name , identifier ) :
2010-12-10 01:20:32 +01:00
if str ( type_name ) . startswith ( ' <module ' ) :
preloadtitle = ' %s . %s ' % ( module_name , identifier )
else :
preloadtitle = ' %s . %s . %s ' % ( module_name , type_name , identifier )
message = " Undocumented (`contribute " \
" <http://wiki.blender.org/index.php/Dev:2.5/Py/API/Documentation/Contribute " \
" ?action=edit§ion=new&preload=Dev:2.5/Py/API/Documentation/Contribute/Howto-message " \
" &preloadtitle= %s >`_) \n \n " % preloadtitle
2010-06-15 04:06:01 +02:00
return message
2010-06-12 00:41:13 +02:00
2009-12-25 16:50:53 +01:00
def range_str ( val ) :
2010-06-15 04:06:01 +02:00
'''
Converts values to strings for the range directive .
( unused function it seems )
'''
2011-02-04 10:27:25 +01:00
if val < - 10000000 :
return ' -inf '
elif val > 10000000 :
return ' inf '
elif type ( val ) == float :
return ' %g ' % val
2009-12-25 16:50:53 +01:00
else :
return str ( val )
2010-02-28 14:45:08 +01:00
2011-02-16 18:31:04 +01:00
def example_extract_docstring ( filepath ) :
file = open ( filepath , ' r ' )
line = file . readline ( )
line_no = 0
text = [ ]
if line . startswith ( ' " " " ' ) : # assume nothing here
line_no + = 1
else :
file . close ( )
return " " , 0
for line in file . readlines ( ) :
line_no + = 1
if line . startswith ( ' " " " ' ) :
break
else :
text . append ( line . rstrip ( ) )
line_no + = 1
file . close ( )
return " \n " . join ( text ) , line_no
2011-03-22 05:28:51 +01:00
def write_title ( fw , text , heading_char ) :
fw ( " %s \n %s \n \n " % ( text , len ( text ) * heading_char ) )
2010-06-15 04:06:01 +02:00
def write_example_ref ( ident , fw , example_id , ext = " py " ) :
2010-02-28 14:45:08 +01:00
if example_id in EXAMPLE_SET :
2011-02-18 09:47:37 +01:00
2011-02-16 18:31:04 +01:00
# extract the comment
filepath = " ../examples/ %s . %s " % ( example_id , ext )
filepath_full = os . path . join ( os . path . dirname ( fw . __self__ . name ) , filepath )
2011-02-18 09:47:37 +01:00
2011-02-16 18:31:04 +01:00
text , line_no = example_extract_docstring ( filepath_full )
2011-02-18 09:47:37 +01:00
2011-02-16 18:31:04 +01:00
for line in text . split ( " \n " ) :
fw ( " %s \n " % ( ident + line ) . rstrip ( ) )
fw ( " \n " )
fw ( " %s .. literalinclude:: %s \n " % ( ident , filepath ) )
2011-02-18 09:47:37 +01:00
if line_no > 0 :
fw ( " %s :lines: %d - \n " % ( ident , line_no ) )
2011-02-16 18:31:04 +01:00
fw ( " \n " )
2010-02-28 14:45:08 +01:00
EXAMPLE_SET_USED . add ( example_id )
else :
if bpy . app . debug :
print ( " \t skipping example: " , example_id )
2011-02-16 18:31:04 +01:00
# Support for numbered files bpy.types.Operator -> bpy.types.Operator.1.py
i = 1
while True :
example_id_num = " %s . %d " % ( example_id , i )
if example_id_num in EXAMPLE_SET :
write_example_ref ( ident , fw , example_id_num , ext )
i + = 1
else :
break
2010-02-28 14:45:08 +01:00
2010-01-31 22:52:26 +01:00
def write_indented_lines ( ident , fn , text , strip = True ) :
2010-06-15 04:06:01 +02:00
'''
Apply same indentation to all lines in a multilines text .
'''
2009-12-25 16:50:53 +01:00
if text is None :
return
for l in text . split ( " \n " ) :
2010-01-31 22:52:26 +01:00
if strip :
fn ( ident + l . strip ( ) + " \n " )
else :
fn ( ident + l + " \n " )
2009-12-25 16:50:53 +01:00
2010-01-22 03:04:25 +01:00
def pymethod2sphinx ( ident , fw , identifier , py_func ) :
'''
class method to sphinx
'''
arg_str = inspect . formatargspec ( * inspect . getargspec ( py_func ) )
if arg_str . startswith ( " (self, " ) :
arg_str = " ( " + arg_str [ 7 : ]
func_type = " method "
elif arg_str . startswith ( " (cls, " ) :
arg_str = " ( " + arg_str [ 6 : ]
func_type = " classmethod "
else :
func_type = " staticmethod "
fw ( ident + " .. %s :: %s %s \n \n " % ( func_type , identifier , arg_str ) )
if py_func . __doc__ :
write_indented_lines ( ident + " " , fw , py_func . __doc__ )
fw ( " \n " )
def pyfunc2sphinx ( ident , fw , identifier , py_func , is_class = True ) :
'''
function or class method to sphinx
'''
arg_str = inspect . formatargspec ( * inspect . getargspec ( py_func ) )
if not is_class :
func_type = " function "
2011-02-04 10:27:25 +01:00
2010-01-22 03:04:25 +01:00
# ther rest are class methods
elif arg_str . startswith ( " (self, " ) :
arg_str = " ( " + arg_str [ 7 : ]
func_type = " method "
elif arg_str . startswith ( " (cls, " ) :
arg_str = " ( " + arg_str [ 6 : ]
func_type = " classmethod "
else :
func_type = " staticmethod "
fw ( ident + " .. %s :: %s %s \n \n " % ( func_type , identifier , arg_str ) )
if py_func . __doc__ :
write_indented_lines ( ident + " " , fw , py_func . __doc__ . strip ( ) )
fw ( " \n " )
2010-04-10 20:35:50 +02:00
2011-02-04 10:27:25 +01:00
def py_descr2sphinx ( ident , fw , descr , module_name , type_name , identifier ) :
2010-07-19 15:36:10 +02:00
if identifier . startswith ( " _ " ) :
return
2011-02-04 10:27:25 +01:00
2010-04-10 20:35:50 +02:00
doc = descr . __doc__
if not doc :
2010-06-15 04:06:01 +02:00
doc = undocumented_message ( module_name , type_name , identifier )
2011-02-04 10:27:25 +01:00
2010-04-10 20:35:50 +02:00
if type ( descr ) == GetSetDescriptorType :
fw ( ident + " .. attribute:: %s \n \n " % identifier )
2010-05-30 02:24:32 +02:00
write_indented_lines ( ident + " " , fw , doc , False )
2010-08-11 19:13:39 +02:00
elif type ( descr ) in ( MethodDescriptorType , ClassMethodDescriptorType ) :
2010-04-10 20:35:50 +02:00
write_indented_lines ( ident , fw , doc , False )
else :
2010-08-11 19:13:39 +02:00
raise TypeError ( " type was not GetSetDescriptorType, MethodDescriptorType or ClassMethodDescriptorType " )
2010-04-10 20:35:50 +02:00
write_example_ref ( ident , fw , module_name + " . " + type_name + " . " + identifier )
fw ( " \n " )
2010-06-15 04:06:01 +02:00
def py_c_func2sphinx ( ident , fw , module_name , type_name , identifier , py_func , is_class = True ) :
2010-01-22 03:04:25 +01:00
'''
c defined function to sphinx .
'''
2011-02-04 10:27:25 +01:00
2010-01-22 03:04:25 +01:00
# dump the docstring, assume its formatted correctly
if py_func . __doc__ :
2010-01-31 22:52:26 +01:00
write_indented_lines ( ident , fw , py_func . __doc__ , False )
2010-01-22 03:04:25 +01:00
fw ( " \n " )
else :
fw ( ident + " .. function:: %s () \n \n " % identifier )
2010-06-15 04:06:01 +02:00
fw ( ident + " " + undocumented_message ( module_name , type_name , identifier ) )
2011-03-14 11:31:50 +01:00
if is_class :
write_example_ref ( ident + " " , fw , module_name + " . " + type_name + " . " + identifier )
else :
write_example_ref ( ident + " " , fw , module_name + " . " + identifier )
fw ( " \n " )
2010-01-22 03:04:25 +01:00
def pyprop2sphinx ( ident , fw , identifier , py_prop ) :
'''
python property to sphinx
'''
2010-06-28 02:06:23 +02:00
# readonly properties use "data" directive, variables use "attribute" directive
if py_prop . fset is None :
fw ( ident + " .. data:: %s \n \n " % identifier )
else :
fw ( ident + " .. attribute:: %s \n \n " % identifier )
2010-01-22 03:04:25 +01:00
write_indented_lines ( ident + " " , fw , py_prop . __doc__ )
if py_prop . fset is None :
fw ( ident + " (readonly) \n \n " )
def pymodule2sphinx ( BASEPATH , module_name , module , title ) :
import types
2010-04-10 21:06:18 +02:00
attribute_set = set ( )
2010-01-22 03:04:25 +01:00
filepath = os . path . join ( BASEPATH , module_name + " .rst " )
2011-02-04 10:27:25 +01:00
2010-01-22 03:04:25 +01:00
file = open ( filepath , " w " )
2010-01-27 22:33:39 +01:00
2010-01-22 03:04:25 +01:00
fw = file . write
2011-02-04 10:27:25 +01:00
2011-03-22 05:28:51 +01:00
write_title ( fw , title , " = " )
2011-02-04 10:27:25 +01:00
2010-01-22 03:04:25 +01:00
fw ( " .. module:: %s \n \n " % module_name )
2011-02-04 10:27:25 +01:00
2010-01-22 03:04:25 +01:00
if module . __doc__ :
# Note, may contain sphinx syntax, dont mangle!
fw ( module . __doc__ . strip ( ) )
fw ( " \n \n " )
2011-02-04 10:27:25 +01:00
2010-02-28 14:45:08 +01:00
write_example_ref ( " " , fw , module_name )
2011-02-04 10:27:25 +01:00
2010-01-31 22:52:26 +01:00
# write members of the module
# only tested with PyStructs which are not exactly modules
2010-04-10 20:35:50 +02:00
for key , descr in sorted ( type ( module ) . __dict__ . items ( ) ) :
2010-12-06 13:36:55 +01:00
if key . startswith ( " __ " ) :
continue
# naughty, we also add getset's into PyStructs, this is not typical py but also not incorrect.
2011-02-04 10:27:25 +01:00
if type ( descr ) == types . GetSetDescriptorType : # 'bpy_app_type' name is only used for examples and messages
2010-12-06 13:36:55 +01:00
py_descr2sphinx ( " " , fw , descr , module_name , " bpy_app_type " , key )
attribute_set . add ( key )
for key , descr in sorted ( type ( module ) . __dict__ . items ( ) ) :
if key . startswith ( " __ " ) :
continue
2010-01-31 22:52:26 +01:00
if type ( descr ) == types . MemberDescriptorType :
if descr . __doc__ :
2010-04-10 20:35:50 +02:00
fw ( " .. data:: %s \n \n " % key )
2010-01-31 22:52:26 +01:00
write_indented_lines ( " " , fw , descr . __doc__ , False )
2010-04-10 21:06:18 +02:00
attribute_set . add ( key )
2010-01-31 22:52:26 +01:00
fw ( " \n " )
2010-04-10 21:06:18 +02:00
del key , descr
2011-02-04 10:27:25 +01:00
Mathutils refactor & include in sphinx generated docs, (TODO, include getset'ers in docs)
- Mathutils.MidpointVecs --> vector.lerp(other, fac)
- Mathutils.AngleBetweenVecs --> vector.angle(other)
- Mathutils.ProjectVecs --> vector.project(other)
- Mathutils.DifferenceQuats --> quat.difference(other)
- Mathutils.Slerp --> quat.slerp(other, fac)
- Mathutils.Rand: removed, use pythons random module
- Mathutils.RotationMatrix(angle, size, axis_flag, axis) --> Mathutils.RotationMatrix(angle, size, axis); merge axis & axis_flag args
- Matrix.scalePart --> Matrix.scale_part
- Matrix.translationPart --> Matrix.translation_part
- Matrix.rotationPart --> Matrix.rotation_part
- toMatrix --> to_matrix
- toEuler --> to_euler
- toQuat --> to_quat
- Vector.toTrackQuat --> Vector.to_track_quat
2010-01-25 10:44:04 +01:00
classes = [ ]
2010-01-22 03:04:25 +01:00
2010-04-06 00:37:09 +02:00
for attribute in sorted ( dir ( module ) ) :
2010-01-22 03:04:25 +01:00
if not attribute . startswith ( " _ " ) :
2010-04-10 21:06:18 +02:00
if attribute in attribute_set :
continue
2011-02-04 10:27:25 +01:00
if attribute . startswith ( " n_ " ) : # annoying exception, needed for bpy.app
2010-04-10 21:06:18 +02:00
continue
2011-02-04 10:27:25 +01:00
2010-01-22 03:04:25 +01:00
value = getattr ( module , attribute )
value_type = type ( value )
Mathutils refactor & include in sphinx generated docs, (TODO, include getset'ers in docs)
- Mathutils.MidpointVecs --> vector.lerp(other, fac)
- Mathutils.AngleBetweenVecs --> vector.angle(other)
- Mathutils.ProjectVecs --> vector.project(other)
- Mathutils.DifferenceQuats --> quat.difference(other)
- Mathutils.Slerp --> quat.slerp(other, fac)
- Mathutils.Rand: removed, use pythons random module
- Mathutils.RotationMatrix(angle, size, axis_flag, axis) --> Mathutils.RotationMatrix(angle, size, axis); merge axis & axis_flag args
- Matrix.scalePart --> Matrix.scale_part
- Matrix.translationPart --> Matrix.translation_part
- Matrix.rotationPart --> Matrix.rotation_part
- toMatrix --> to_matrix
- toEuler --> to_euler
- toQuat --> to_quat
- Vector.toTrackQuat --> Vector.to_track_quat
2010-01-25 10:44:04 +01:00
2010-01-22 03:04:25 +01:00
if value_type == types . FunctionType :
pyfunc2sphinx ( " " , fw , attribute , value , is_class = False )
2011-02-04 10:27:25 +01:00
elif value_type in ( types . BuiltinMethodType , types . BuiltinFunctionType ) : # both the same at the moment but to be future proof
2010-01-22 03:04:25 +01:00
# note: can't get args from these, so dump the string as is
# this means any module used like this must have fully formatted docstrings.
2011-03-14 11:31:50 +01:00
py_c_func2sphinx ( " " , fw , module_name , None , attribute , value , is_class = False )
Mathutils refactor & include in sphinx generated docs, (TODO, include getset'ers in docs)
- Mathutils.MidpointVecs --> vector.lerp(other, fac)
- Mathutils.AngleBetweenVecs --> vector.angle(other)
- Mathutils.ProjectVecs --> vector.project(other)
- Mathutils.DifferenceQuats --> quat.difference(other)
- Mathutils.Slerp --> quat.slerp(other, fac)
- Mathutils.Rand: removed, use pythons random module
- Mathutils.RotationMatrix(angle, size, axis_flag, axis) --> Mathutils.RotationMatrix(angle, size, axis); merge axis & axis_flag args
- Matrix.scalePart --> Matrix.scale_part
- Matrix.translationPart --> Matrix.translation_part
- Matrix.rotationPart --> Matrix.rotation_part
- toMatrix --> to_matrix
- toEuler --> to_euler
- toQuat --> to_quat
- Vector.toTrackQuat --> Vector.to_track_quat
2010-01-25 10:44:04 +01:00
elif value_type == type :
classes . append ( ( attribute , value ) )
2010-04-06 00:37:09 +02:00
elif value_type in ( bool , int , float , str , tuple ) :
# constant, not much fun we can do here except to list it.
# TODO, figure out some way to document these!
fw ( " .. data:: %s \n \n " % attribute )
write_indented_lines ( " " , fw , " constant value %s " % repr ( value ) , False )
fw ( " \n " )
else :
print ( " \t not documenting %s . %s " % ( module_name , attribute ) )
2010-04-10 21:06:18 +02:00
continue
attribute_set . add ( attribute )
2010-01-22 03:04:25 +01:00
# TODO, more types...
2010-04-10 20:35:50 +02:00
Mathutils refactor & include in sphinx generated docs, (TODO, include getset'ers in docs)
- Mathutils.MidpointVecs --> vector.lerp(other, fac)
- Mathutils.AngleBetweenVecs --> vector.angle(other)
- Mathutils.ProjectVecs --> vector.project(other)
- Mathutils.DifferenceQuats --> quat.difference(other)
- Mathutils.Slerp --> quat.slerp(other, fac)
- Mathutils.Rand: removed, use pythons random module
- Mathutils.RotationMatrix(angle, size, axis_flag, axis) --> Mathutils.RotationMatrix(angle, size, axis); merge axis & axis_flag args
- Matrix.scalePart --> Matrix.scale_part
- Matrix.translationPart --> Matrix.translation_part
- Matrix.rotationPart --> Matrix.rotation_part
- toMatrix --> to_matrix
- toEuler --> to_euler
- toQuat --> to_quat
- Vector.toTrackQuat --> Vector.to_track_quat
2010-01-25 10:44:04 +01:00
# write collected classes now
2010-04-10 20:35:50 +02:00
for ( type_name , value ) in classes :
Mathutils refactor & include in sphinx generated docs, (TODO, include getset'ers in docs)
- Mathutils.MidpointVecs --> vector.lerp(other, fac)
- Mathutils.AngleBetweenVecs --> vector.angle(other)
- Mathutils.ProjectVecs --> vector.project(other)
- Mathutils.DifferenceQuats --> quat.difference(other)
- Mathutils.Slerp --> quat.slerp(other, fac)
- Mathutils.Rand: removed, use pythons random module
- Mathutils.RotationMatrix(angle, size, axis_flag, axis) --> Mathutils.RotationMatrix(angle, size, axis); merge axis & axis_flag args
- Matrix.scalePart --> Matrix.scale_part
- Matrix.translationPart --> Matrix.translation_part
- Matrix.rotationPart --> Matrix.rotation_part
- toMatrix --> to_matrix
- toEuler --> to_euler
- toQuat --> to_quat
- Vector.toTrackQuat --> Vector.to_track_quat
2010-01-25 10:44:04 +01:00
# May need to be its own function
2010-04-10 20:35:50 +02:00
fw ( " .. class:: %s \n \n " % type_name )
Mathutils refactor & include in sphinx generated docs, (TODO, include getset'ers in docs)
- Mathutils.MidpointVecs --> vector.lerp(other, fac)
- Mathutils.AngleBetweenVecs --> vector.angle(other)
- Mathutils.ProjectVecs --> vector.project(other)
- Mathutils.DifferenceQuats --> quat.difference(other)
- Mathutils.Slerp --> quat.slerp(other, fac)
- Mathutils.Rand: removed, use pythons random module
- Mathutils.RotationMatrix(angle, size, axis_flag, axis) --> Mathutils.RotationMatrix(angle, size, axis); merge axis & axis_flag args
- Matrix.scalePart --> Matrix.scale_part
- Matrix.translationPart --> Matrix.translation_part
- Matrix.rotationPart --> Matrix.rotation_part
- toMatrix --> to_matrix
- toEuler --> to_euler
- toQuat --> to_quat
- Vector.toTrackQuat --> Vector.to_track_quat
2010-01-25 10:44:04 +01:00
if value . __doc__ :
2010-01-31 22:52:26 +01:00
write_indented_lines ( " " , fw , value . __doc__ , False )
2010-01-27 22:33:39 +01:00
fw ( " \n " )
2010-04-10 20:35:50 +02:00
write_example_ref ( " " , fw , module_name + " . " + type_name )
Mathutils refactor & include in sphinx generated docs, (TODO, include getset'ers in docs)
- Mathutils.MidpointVecs --> vector.lerp(other, fac)
- Mathutils.AngleBetweenVecs --> vector.angle(other)
- Mathutils.ProjectVecs --> vector.project(other)
- Mathutils.DifferenceQuats --> quat.difference(other)
- Mathutils.Slerp --> quat.slerp(other, fac)
- Mathutils.Rand: removed, use pythons random module
- Mathutils.RotationMatrix(angle, size, axis_flag, axis) --> Mathutils.RotationMatrix(angle, size, axis); merge axis & axis_flag args
- Matrix.scalePart --> Matrix.scale_part
- Matrix.translationPart --> Matrix.translation_part
- Matrix.rotationPart --> Matrix.rotation_part
- toMatrix --> to_matrix
- toEuler --> to_euler
- toQuat --> to_quat
- Vector.toTrackQuat --> Vector.to_track_quat
2010-01-25 10:44:04 +01:00
2010-04-10 20:35:50 +02:00
descr_items = [ ( key , descr ) for key , descr in sorted ( value . __dict__ . items ( ) ) if not key . startswith ( " __ " ) ]
2010-08-11 19:13:39 +02:00
for key , descr in descr_items :
2010-08-12 00:36:43 +02:00
if type ( descr ) == ClassMethodDescriptorType :
2010-08-11 19:13:39 +02:00
py_descr2sphinx ( " " , fw , descr , module_name , type_name , key )
2010-04-10 20:35:50 +02:00
for key , descr in descr_items :
2010-08-12 00:36:43 +02:00
if type ( descr ) == MethodDescriptorType :
2010-04-10 20:35:50 +02:00
py_descr2sphinx ( " " , fw , descr , module_name , type_name , key )
for key , descr in descr_items :
if type ( descr ) == GetSetDescriptorType :
py_descr2sphinx ( " " , fw , descr , module_name , type_name , key )
Mathutils refactor & include in sphinx generated docs, (TODO, include getset'ers in docs)
- Mathutils.MidpointVecs --> vector.lerp(other, fac)
- Mathutils.AngleBetweenVecs --> vector.angle(other)
- Mathutils.ProjectVecs --> vector.project(other)
- Mathutils.DifferenceQuats --> quat.difference(other)
- Mathutils.Slerp --> quat.slerp(other, fac)
- Mathutils.Rand: removed, use pythons random module
- Mathutils.RotationMatrix(angle, size, axis_flag, axis) --> Mathutils.RotationMatrix(angle, size, axis); merge axis & axis_flag args
- Matrix.scalePart --> Matrix.scale_part
- Matrix.translationPart --> Matrix.translation_part
- Matrix.rotationPart --> Matrix.rotation_part
- toMatrix --> to_matrix
- toEuler --> to_euler
- toQuat --> to_quat
- Vector.toTrackQuat --> Vector.to_track_quat
2010-01-25 10:44:04 +01:00
fw ( " \n \n " )
2010-01-22 03:04:25 +01:00
file . close ( )
2011-02-15 16:37:40 +01:00
def pycontext2sphinx ( BASEPATH ) :
# Only use once. very irregular
filepath = os . path . join ( BASEPATH , " bpy.context.rst " )
file = open ( filepath , " w " )
fw = file . write
fw ( " Context Access (bpy.context) \n " )
fw ( " ============================ \n \n " )
fw ( " .. module:: bpy.context \n " )
fw ( " \n " )
fw ( " The context members available depend on the area of blender which is currently being accessed. \n " )
fw ( " \n " )
fw ( " Note that all context values are readonly, but may be modified through the data api or by running operators \n \n " )
# nasty, get strings directly from blender because there is no other way to get it
import ctypes
context_strings = (
" screen_context_dir " ,
" view3d_context_dir " ,
" buttons_context_dir " ,
" image_context_dir " ,
" node_context_dir " ,
" text_context_dir " ,
)
# Changes in blender will force errors here
type_map = {
" active_base " : ( " ObjectBase " , False ) ,
" active_bone " : ( " Bone " , False ) ,
" active_object " : ( " Object " , False ) ,
" active_pose_bone " : ( " PoseBone " , False ) ,
" armature " : ( " Armature " , False ) ,
" bone " : ( " Bone " , False ) ,
" brush " : ( " Brush " , False ) ,
" camera " : ( " Camera " , False ) ,
" cloth " : ( " ClothModifier " , False ) ,
" collision " : ( " CollisionModifier " , False ) ,
" curve " : ( " Curve " , False ) ,
" edit_bone " : ( " EditBone " , False ) ,
" edit_image " : ( " Image " , False ) ,
" edit_object " : ( " Object " , False ) ,
" edit_text " : ( " Text " , False ) ,
" editable_bones " : ( " EditBone " , True ) ,
" fluid " : ( " FluidSimulationModifier " , False ) ,
" lamp " : ( " Lamp " , False ) ,
" lattice " : ( " Lattice " , False ) ,
" material " : ( " Material " , False ) ,
" material_slot " : ( " MaterialSlot " , False ) ,
" mesh " : ( " Mesh " , False ) ,
" meta_ball " : ( " MetaBall " , False ) ,
" object " : ( " Object " , False ) ,
" particle_edit_object " : ( " Object " , False ) ,
" particle_system " : ( " ParticleSystem " , False ) ,
" particle_system_editable " : ( " ParticleSystem " , False ) ,
" pose_bone " : ( " PoseBone " , False ) ,
" scene " : ( " Scene " , False ) ,
" sculpt_object " : ( " Object " , False ) ,
" selectable_bases " : ( " ObjectBase " , True ) ,
" selectable_objects " : ( " Object " , True ) ,
" selected_bases " : ( " ObjectBase " , True ) ,
" selected_bones " : ( " Bone " , True ) ,
" selected_editable_bases " : ( " ObjectBase " , True ) ,
" selected_editable_bones " : ( " Bone " , True ) ,
" selected_editable_objects " : ( " Object " , True ) ,
" selected_editable_sequences " : ( " Sequence " , True ) ,
" selected_nodes " : ( " Node " , True ) ,
" selected_objects " : ( " Object " , True ) ,
" selected_pose_bones " : ( " PoseBone " , True ) ,
" selected_sequences " : ( " Sequence " , True ) ,
" sequences " : ( " Sequence " , True ) ,
" smoke " : ( " SmokeModifier " , False ) ,
" soft_body " : ( " SoftBodyModifier " , False ) ,
" texture " : ( " Texture " , False ) ,
" texture_paint_object " : ( " Object " , False ) ,
" texture_slot " : ( " MaterialTextureSlot " , False ) ,
" vertex_paint_object " : ( " Object " , False ) ,
" visible_bases " : ( " ObjectBase " , True ) ,
" visible_bones " : ( " Object " , True ) ,
" visible_objects " : ( " Object " , True ) ,
" visible_pose_bones " : ( " PoseBone " , True ) ,
" weight_paint_object " : ( " Object " , False ) ,
" world " : ( " World " , False ) ,
}
unique = set ( )
blend_cdll = ctypes . CDLL ( " " )
for ctx_str in context_strings :
subsection = " %s Context " % ctx_str . split ( " _ " ) [ 0 ] . title ( )
fw ( " \n %s \n %s \n \n " % ( subsection , ( len ( subsection ) * ' - ' ) ) )
attr = ctypes . addressof ( getattr ( blend_cdll , ctx_str ) )
c_char_p_p = ctypes . POINTER ( ctypes . c_char_p )
char_array = c_char_p_p . from_address ( attr )
i = 0
while char_array [ i ] is not None :
member = ctypes . string_at ( char_array [ i ] ) . decode ( )
fw ( " .. data:: %s \n \n " % member )
member_type , is_seq = type_map [ member ]
fw ( " :type: %s :class:`bpy.types. %s ` \n \n " % ( " sequence of " if is_seq else " " , member_type ) )
unique . add ( member )
i + = 1
# generate typemap...
# for member in sorted(unique):
# print(' "%s": ("", False),' % member)
if len ( type_map ) > len ( unique ) :
raise Exception ( " Some types are not used: %s " % str ( [ member for member in type_map if member not in unique ] ) )
else :
2011-02-16 03:25:03 +01:00
pass # will have raised an error above
2011-02-15 16:37:40 +01:00
2011-02-22 06:23:20 +01:00
file . close ( )
2011-02-15 16:37:40 +01:00
2011-02-16 06:18:10 +01:00
def pyrna2sphinx ( BASEPATH ) :
""" bpy.types and bpy.ops
"""
2009-12-25 16:50:53 +01:00
structs , funcs , ops , props = rna_info . BuildRNAInfo ( )
2011-02-16 06:18:10 +01:00
if FILTER_BPY_TYPES is not None :
structs = { k : v for k , v in structs . items ( ) if k [ 1 ] in FILTER_BPY_TYPES }
2009-12-25 16:50:53 +01:00
2011-02-16 06:18:10 +01:00
if FILTER_BPY_OPS is not None :
ops = { k : v for k , v in ops . items ( ) if v . module_name in FILTER_BPY_OPS }
2009-12-25 16:50:53 +01:00
2009-12-26 17:47:25 +01:00
def write_param ( ident , fw , prop , is_return = False ) :
if is_return :
id_name = " return "
id_type = " rtype "
2011-03-22 05:28:51 +01:00
kwargs = { " as_ret " : True }
2010-01-18 11:45:54 +01:00
identifier = " "
2009-12-25 16:50:53 +01:00
else :
2009-12-26 17:47:25 +01:00
id_name = " arg "
id_type = " type "
2011-03-22 05:28:51 +01:00
kwargs = { " as_arg " : True }
2010-01-18 11:45:54 +01:00
identifier = " %s " % prop . identifier
2009-12-25 16:50:53 +01:00
2011-03-22 05:28:51 +01:00
kwargs [ " class_fmt " ] = " :class:` %s ` "
kwargs [ " collection_id " ] = _BPY_PROP_COLLECTION_ID
2010-01-18 11:45:54 +01:00
type_descr = prop . get_type_description ( * * kwargs )
2009-12-26 17:47:25 +01:00
if prop . name or prop . description :
2010-09-19 09:07:14 +02:00
fw ( ident + " : %s %s : %s \n " % ( id_name , identifier , " , " . join ( val for val in ( prop . name , prop . description ) if val ) ) )
2010-01-18 11:45:54 +01:00
fw ( ident + " : %s %s : %s \n " % ( id_type , identifier , type_descr ) )
2009-12-25 16:50:53 +01:00
def write_struct ( struct ) :
#if not struct.identifier.startswith("Sc") and not struct.identifier.startswith("I"):
# return
2010-01-02 20:01:19 +01:00
#if not struct.identifier == "Object":
# return
2009-12-25 16:50:53 +01:00
filepath = os . path . join ( BASEPATH , " bpy.types. %s .rst " % struct . identifier )
file = open ( filepath , " w " )
fw = file . write
2011-02-04 10:27:25 +01:00
2010-04-10 20:35:50 +02:00
base_id = getattr ( struct . base , " identifier " , " " )
if _BPY_STRUCT_FAKE :
if not base_id :
base_id = _BPY_STRUCT_FAKE
if base_id :
title = " %s ( %s ) " % ( struct . identifier , base_id )
2009-12-25 16:50:53 +01:00
else :
title = struct . identifier
2011-03-22 05:28:51 +01:00
write_title ( fw , title , " = " )
2011-02-04 10:27:25 +01:00
2009-12-25 16:50:53 +01:00
fw ( " .. module:: bpy.types \n \n " )
2011-02-04 10:27:25 +01:00
2011-02-18 09:47:37 +01:00
# docs first?, ok
2011-02-16 18:31:04 +01:00
write_example_ref ( " " , fw , " bpy.types. %s " % struct . identifier )
2010-04-10 20:35:50 +02:00
base_ids = [ base . identifier for base in struct . get_bases ( ) ]
if _BPY_STRUCT_FAKE :
base_ids . append ( _BPY_STRUCT_FAKE )
base_ids . reverse ( )
2011-02-04 10:27:25 +01:00
2010-04-10 20:35:50 +02:00
if base_ids :
if len ( base_ids ) > 1 :
2009-12-25 16:50:53 +01:00
fw ( " base classes --- " )
else :
fw ( " base class --- " )
2010-09-19 09:07:14 +02:00
fw ( " , " . join ( ( " :class:` %s ` " % base_id ) for base_id in base_ids ) )
2009-12-25 16:50:53 +01:00
fw ( " \n \n " )
2011-02-04 10:27:25 +01:00
2010-04-10 20:35:50 +02:00
subclass_ids = [ s . identifier for s in structs . values ( ) if s . base is struct if not rna_info . rna_id_ignore ( s . identifier ) ]
if subclass_ids :
2010-09-19 09:07:14 +02:00
fw ( " subclasses --- \n " + " , " . join ( ( " :class:` %s ` " % s ) for s in subclass_ids ) + " \n \n " )
2011-02-04 10:27:25 +01:00
2010-04-10 20:35:50 +02:00
base_id = getattr ( struct . base , " identifier " , " " )
2011-02-04 10:27:25 +01:00
2010-04-10 20:35:50 +02:00
if _BPY_STRUCT_FAKE :
if not base_id :
base_id = _BPY_STRUCT_FAKE
2009-12-25 16:50:53 +01:00
2010-04-10 20:35:50 +02:00
if base_id :
fw ( " .. class:: %s ( %s ) \n \n " % ( struct . identifier , base_id ) )
2009-12-25 16:50:53 +01:00
else :
fw ( " .. class:: %s \n \n " % struct . identifier )
fw ( " %s \n \n " % struct . description )
2011-02-04 10:27:25 +01:00
2010-06-28 02:06:23 +02:00
# properties sorted in alphabetical order
2010-07-15 13:51:43 +02:00
sorted_struct_properties = struct . properties [ : ]
sorted_struct_properties . sort ( key = lambda prop : prop . identifier )
2010-06-28 02:06:23 +02:00
for prop in sorted_struct_properties :
2011-03-22 05:28:51 +01:00
type_descr = prop . get_type_description ( class_fmt = " :class:` %s ` " , collection_id = _BPY_PROP_COLLECTION_ID )
2010-06-28 02:06:23 +02:00
# readonly properties use "data" directive, variables properties use "attribute" directive
if ' readonly ' in type_descr :
fw ( " .. data:: %s \n \n " % prop . identifier )
else :
fw ( " .. attribute:: %s \n \n " % prop . identifier )
2009-12-26 17:47:25 +01:00
if prop . description :
fw ( " %s \n \n " % prop . description )
2010-06-02 23:28:17 +02:00
fw ( " :type: %s \n \n " % type_descr )
2011-02-04 10:27:25 +01:00
2009-12-25 16:50:53 +01:00
# python attributes
py_properties = struct . get_py_properties ( )
py_prop = None
for identifier , py_prop in py_properties :
2010-01-22 03:04:25 +01:00
pyprop2sphinx ( " " , fw , identifier , py_prop )
2009-12-25 16:50:53 +01:00
del py_properties , py_prop
for func in struct . functions :
2010-09-19 09:07:14 +02:00
args_str = " , " . join ( prop . get_arg_default ( force = False ) for prop in func . args )
2009-12-25 16:50:53 +01:00
2010-08-17 16:32:14 +02:00
fw ( " .. %s :: %s ( %s ) \n \n " % ( " classmethod " if func . is_classmethod else " method " , func . identifier , args_str ) )
2009-12-25 16:50:53 +01:00
fw ( " %s \n \n " % func . description )
2011-02-04 10:27:25 +01:00
2009-12-25 16:50:53 +01:00
for prop in func . args :
2009-12-26 17:47:25 +01:00
write_param ( " " , fw , prop )
2010-01-02 19:55:07 +01:00
if len ( func . return_values ) == 1 :
write_param ( " " , fw , func . return_values [ 0 ] , is_return = True )
2011-02-04 10:27:25 +01:00
elif func . return_values : # multiple return values
2010-09-19 09:07:14 +02:00
fw ( " :return ( %s ): \n " % " , " . join ( prop . identifier for prop in func . return_values ) )
2010-01-02 19:55:07 +01:00
for prop in func . return_values :
2011-03-22 05:28:51 +01:00
type_descr = prop . get_type_description ( as_ret = True , class_fmt = " :class:` %s ` " , collection_id = _BPY_PROP_COLLECTION_ID )
2010-01-02 19:55:07 +01:00
descr = prop . description
if not descr :
descr = prop . name
2010-01-17 21:59:35 +01:00
fw ( " ` %s `, %s , %s \n \n " % ( prop . identifier , descr , type_descr ) )
2010-01-02 19:55:07 +01:00
2009-12-26 17:47:25 +01:00
fw ( " \n " )
2009-12-25 16:50:53 +01:00
# python methods
py_funcs = struct . get_py_functions ( )
py_func = None
2011-02-04 10:27:25 +01:00
2009-12-25 16:50:53 +01:00
for identifier , py_func in py_funcs :
2010-01-22 03:04:25 +01:00
pyfunc2sphinx ( " " , fw , identifier , py_func , is_class = True )
2009-12-25 16:50:53 +01:00
del py_funcs , py_func
2011-03-14 11:31:50 +01:00
py_funcs = struct . get_py_c_functions ( )
py_func = None
for identifier , py_func in py_funcs :
py_c_func2sphinx ( " " , fw , " bpy.types " , struct . identifier , identifier , py_func , is_class = True )
2010-04-09 22:43:58 +02:00
lines = [ ]
2010-04-10 20:35:50 +02:00
if struct . base or _BPY_STRUCT_FAKE :
2010-04-09 22:43:58 +02:00
bases = list ( reversed ( struct . get_bases ( ) ) )
2010-04-10 20:35:50 +02:00
2010-04-09 22:43:58 +02:00
# props
lines [ : ] = [ ]
2011-02-04 10:27:25 +01:00
2010-04-10 20:35:50 +02:00
if _BPY_STRUCT_FAKE :
descr_items = [ ( key , descr ) for key , descr in sorted ( bpy . types . Struct . __bases__ [ 0 ] . __dict__ . items ( ) ) if not key . startswith ( " __ " ) ]
2011-02-04 10:27:25 +01:00
2010-04-10 20:35:50 +02:00
if _BPY_STRUCT_FAKE :
for key , descr in descr_items :
if type ( descr ) == GetSetDescriptorType :
2010-09-03 11:21:40 +02:00
lines . append ( " * :class:` %s . %s ` \n " % ( _BPY_STRUCT_FAKE , key ) )
2010-04-10 20:35:50 +02:00
2010-04-09 22:43:58 +02:00
for base in bases :
for prop in base . properties :
2010-09-03 11:21:40 +02:00
lines . append ( " * :class:` %s . %s ` \n " % ( base . identifier , prop . identifier ) )
2010-04-09 22:43:58 +02:00
for identifier , py_prop in base . get_py_properties ( ) :
2010-09-03 11:21:40 +02:00
lines . append ( " * :class:` %s . %s ` \n " % ( base . identifier , identifier ) )
2011-02-04 10:27:25 +01:00
2010-04-10 20:35:50 +02:00
for identifier , py_prop in base . get_py_properties ( ) :
2010-09-03 11:21:40 +02:00
lines . append ( " * :class:` %s . %s ` \n " % ( base . identifier , identifier ) )
2011-02-04 10:27:25 +01:00
2010-04-09 22:43:58 +02:00
if lines :
fw ( " .. rubric:: Inherited Properties \n \n " )
2010-09-03 11:21:40 +02:00
fw ( " .. hlist:: \n " )
2010-09-03 16:53:54 +02:00
fw ( " :columns: 2 \n \n " )
2010-09-03 11:21:40 +02:00
2010-04-09 22:43:58 +02:00
for line in lines :
fw ( line )
fw ( " \n " )
# funcs
lines [ : ] = [ ]
2010-04-10 20:35:50 +02:00
if _BPY_STRUCT_FAKE :
for key , descr in descr_items :
if type ( descr ) == MethodDescriptorType :
2010-09-03 11:21:40 +02:00
lines . append ( " * :class:` %s . %s ` \n " % ( _BPY_STRUCT_FAKE , key ) )
2010-04-10 20:35:50 +02:00
2010-04-09 22:43:58 +02:00
for base in bases :
for func in base . functions :
2010-09-03 11:21:40 +02:00
lines . append ( " * :class:` %s . %s ` \n " % ( base . identifier , func . identifier ) )
2010-04-09 22:43:58 +02:00
for identifier , py_func in base . get_py_functions ( ) :
2010-09-03 11:21:40 +02:00
lines . append ( " * :class:` %s . %s ` \n " % ( base . identifier , identifier ) )
2010-04-09 22:43:58 +02:00
if lines :
fw ( " .. rubric:: Inherited Functions \n \n " )
2010-09-03 11:21:40 +02:00
fw ( " .. hlist:: \n " )
2010-09-03 16:53:54 +02:00
fw ( " :columns: 2 \n \n " )
2010-09-03 11:21:40 +02:00
2010-04-09 22:43:58 +02:00
for line in lines :
fw ( line )
fw ( " \n " )
2011-02-04 10:27:25 +01:00
lines [ : ] = [ ]
2010-04-09 22:43:58 +02:00
2009-12-25 16:50:53 +01:00
if struct . references :
# use this otherwise it gets in the index for a normal heading.
fw ( " .. rubric:: References \n \n " )
2010-09-03 11:21:40 +02:00
fw ( " .. hlist:: \n " )
2010-09-03 16:53:54 +02:00
fw ( " :columns: 2 \n \n " )
2010-09-03 11:21:40 +02:00
2009-12-25 16:50:53 +01:00
for ref in struct . references :
ref_split = ref . split ( " . " )
if len ( ref_split ) > 2 :
ref = ref_split [ - 2 ] + " . " + ref_split [ - 1 ]
2010-09-03 11:21:40 +02:00
fw ( " * :class:` %s ` \n " % ref )
2009-12-25 16:50:53 +01:00
fw ( " \n " )
2011-02-18 09:47:37 +01:00
# docs last?, disable for now
# write_example_ref("", fw, "bpy.types.%s" % struct.identifier)
2011-02-22 06:23:20 +01:00
file . close ( )
2011-02-18 09:47:37 +01:00
2011-02-16 06:18:10 +01:00
if " bpy.types " not in EXCLUDE_MODULES :
for struct in structs . values ( ) :
# TODO, rna_info should filter these out!
if " _OT_ " in struct . identifier :
continue
write_struct ( struct )
2011-02-04 10:27:25 +01:00
2011-03-22 05:28:51 +01:00
def fake_bpy_type ( class_value , class_name , descr_str , use_subclasses = True ) :
filepath = os . path . join ( BASEPATH , " bpy.types. %s .rst " % class_name )
2011-02-16 06:18:10 +01:00
file = open ( filepath , " w " )
fw = file . write
2010-04-10 20:35:50 +02:00
2011-03-22 05:28:51 +01:00
write_title ( fw , class_name , " = " )
2011-02-16 06:18:10 +01:00
fw ( " .. module:: bpy.types \n " )
fw ( " \n " )
2010-04-10 20:35:50 +02:00
2011-03-22 05:28:51 +01:00
if use_subclasses :
subclass_ids = [ s . identifier for s in structs . values ( ) if s . base is None if not rna_info . rna_id_ignore ( s . identifier ) ]
if subclass_ids :
fw ( " subclasses --- \n " + " , " . join ( ( " :class:` %s ` " % s ) for s in sorted ( subclass_ids ) ) + " \n \n " )
2010-04-10 20:35:50 +02:00
2011-03-22 05:28:51 +01:00
fw ( " .. class:: %s \n \n " % class_name )
fw ( " %s \n \n " % descr_str )
2011-02-16 06:18:10 +01:00
fw ( " .. note:: \n \n " )
2011-03-22 05:28:51 +01:00
fw ( " Note that bpy.types. %s is not actually available from within blender, it only exists for the purpose of documentation. \n \n " % class_name )
2010-04-10 20:35:50 +02:00
2011-03-22 05:28:51 +01:00
descr_items = [ ( key , descr ) for key , descr in sorted ( class_value . __dict__ . items ( ) ) if not key . startswith ( " __ " ) ]
2010-04-10 20:35:50 +02:00
2011-02-16 06:18:10 +01:00
for key , descr in descr_items :
if type ( descr ) == MethodDescriptorType : # GetSetDescriptorType, GetSetDescriptorType's are not documented yet
2011-03-22 05:28:51 +01:00
py_descr2sphinx ( " " , fw , descr , " bpy.types " , class_name , key )
2010-04-10 20:35:50 +02:00
2011-02-16 06:18:10 +01:00
for key , descr in descr_items :
if type ( descr ) == GetSetDescriptorType :
2011-03-22 05:28:51 +01:00
py_descr2sphinx ( " " , fw , descr , " bpy.types " , class_name , key )
2011-02-22 06:23:20 +01:00
file . close ( )
2010-04-10 20:35:50 +02:00
2011-03-22 05:28:51 +01:00
# write fake classes
if _BPY_STRUCT_FAKE :
class_value = bpy . types . Struct . __bases__ [ 0 ]
fake_bpy_type ( class_value , _BPY_STRUCT_FAKE , " built-in base class for all classes in bpy.types. " , use_subclasses = True )
if _BPY_PROP_COLLECTION_FAKE :
class_value = bpy . data . objects . __class__
fake_bpy_type ( class_value , _BPY_PROP_COLLECTION_FAKE , " built-in class used for all collections. " , use_subclasses = False )
2010-06-04 15:47:56 +02:00
# operators
2009-12-25 16:50:53 +01:00
def write_ops ( ) :
2011-02-04 10:27:25 +01:00
API_BASEURL = " https://svn.blender.org/svnroot/bf-blender/trunk/blender/release/scripts "
2011-02-22 06:23:20 +01:00
op_modules = { }
for op in ops . values ( ) :
op_modules . setdefault ( op . module_name , [ ] ) . append ( op )
del op
2011-02-25 17:19:50 +01:00
2011-02-22 06:23:20 +01:00
for op_module_name , ops_mod in op_modules . items ( ) :
filepath = os . path . join ( BASEPATH , " bpy.ops. %s .rst " % op_module_name )
file = open ( filepath , " w " )
fw = file . write
title = " %s Operators " % op_module_name . replace ( " _ " , " " ) . title ( )
2011-03-22 05:28:51 +01:00
write_title ( fw , title , " = " )
2011-02-04 10:27:25 +01:00
2011-02-22 06:23:20 +01:00
fw ( " .. module:: bpy.ops. %s \n \n " % op_module_name )
2011-02-04 10:27:25 +01:00
2011-02-22 06:23:20 +01:00
ops_mod . sort ( key = lambda op : op . func_name )
2011-02-04 10:27:25 +01:00
2011-02-22 06:23:20 +01:00
for op in ops_mod :
args_str = " , " . join ( prop . get_arg_default ( force = True ) for prop in op . args )
fw ( " .. function:: %s ( %s ) \n \n " % ( op . func_name , args_str ) )
2010-04-10 20:35:50 +02:00
2011-02-22 06:23:20 +01:00
# if the description isn't valid, we output the standard warning
# with a link to the wiki so that people can help
if not op . description or op . description == " (undocumented operator) " :
operator_description = undocumented_message ( ' bpy.ops ' , op . module_name , op . func_name )
else :
operator_description = op . description
2010-06-12 00:41:13 +02:00
2011-02-22 06:23:20 +01:00
fw ( " %s \n \n " % operator_description )
for prop in op . args :
write_param ( " " , fw , prop )
if op . args :
fw ( " \n " )
2010-06-12 00:41:13 +02:00
2011-02-22 06:23:20 +01:00
location = op . get_location ( )
if location != ( None , None ) :
fw ( " :file: ` %s < %s / %s >`_: %d \n \n " % ( location [ 0 ] , API_BASEURL , location [ 0 ] , location [ 1 ] ) )
2009-12-26 17:47:25 +01:00
2011-02-22 06:23:20 +01:00
file . close ( )
2011-02-04 10:27:25 +01:00
2011-02-16 06:18:10 +01:00
if " bpy.ops " not in EXCLUDE_MODULES :
write_ops ( )
def rna2sphinx ( BASEPATH ) :
try :
os . mkdir ( BASEPATH )
except :
pass
# conf.py - empty for now
filepath = os . path . join ( BASEPATH , " conf.py " )
file = open ( filepath , " w " )
fw = file . write
version_string = " . " . join ( str ( v ) for v in bpy . app . version )
if bpy . app . build_revision != " Unknown " :
version_string = version_string + " r " + bpy . app . build_revision
# for use with files
version_string_fp = " _ " . join ( str ( v ) for v in bpy . app . version )
fw ( " project = ' Blender ' \n " )
# fw("master_doc = 'index'\n")
fw ( " copyright = u ' Blender Foundation ' \n " )
fw ( " version = ' %s - UNSTABLE API ' \n " % version_string )
fw ( " release = ' %s - UNSTABLE API ' \n " % version_string )
fw ( " html_theme = ' blender-org ' \n " )
fw ( " html_theme_path = [ ' ../ ' ] \n " )
fw ( " html_favicon = ' favicon.ico ' \n " )
# not helpful since the source us generated, adds to upload size.
fw ( " html_copy_source = False \n " )
fw ( " \n " )
# needed for latex, pdf gen
fw ( " latex_documents = [ ( ' contents ' , ' contents.tex ' , ' Blender Index ' , ' Blender Foundation ' , ' manual ' ), ] \n " )
fw ( " latex_paper_size = ' a4paper ' \n " )
file . close ( )
# main page needed for sphinx (index.html)
filepath = os . path . join ( BASEPATH , " contents.rst " )
file = open ( filepath , " w " )
fw = file . write
fw ( " %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% % \n " )
fw ( " Blender Documentation contents \n " )
fw ( " %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% % \n " )
fw ( " \n " )
fw ( " This document is an API reference for Blender %s . built %s . \n " % ( version_string , bpy . app . build_date ) )
fw ( " \n " )
2011-02-18 09:47:37 +01:00
fw ( " | An introduction to Blender and Python can be found at `Quickstart Intro <http://wiki.blender.org/index.php/Dev:2.5/Py/API/Intro>`_, \n " )
fw ( " | For a more general explanation of blender/python see the `API Overview <http://wiki.blender.org/index.php/Dev:2.5/Py/API/Overview>`_ \n " )
2011-02-16 06:18:10 +01:00
fw ( " \n " )
2011-02-18 09:47:37 +01:00
fw ( " `A PDF version of this document is also available <blender_python_reference_ %s .pdf>`_ \n " % version_string_fp )
2011-02-16 06:18:10 +01:00
fw ( " \n " )
fw ( " .. warning:: The Python API in Blender is **UNSTABLE**, It should only be used for testing, any script written now may break in future releases. \n " )
fw ( " \n " )
fw ( " The following areas are subject to change. \n " )
fw ( " * operator names and arguments \n " )
fw ( " * render api \n " )
fw ( " * function calls with the data api (any function calls with values accessed from bpy.data), including functions for importing and exporting meshes \n " )
fw ( " * class registration (Operator, Panels, Menus, Headers) \n " )
fw ( " * modules: bpy.props, blf) \n " )
fw ( " * members in the bpy.context have to be reviewed \n " )
fw ( " * python defined modal operators, especially drawing callbacks are highly experemental \n " )
fw ( " \n " )
fw ( " These parts of the API are relatively stable and are unlikely to change significantly \n " )
fw ( " * data API, access to attributes of blender data such as mesh verts, material color, timeline frames and scene objects \n " )
fw ( " * user interface functions for defining buttons, creation of menus, headers, panels \n " )
fw ( " * modules: bgl and mathutils \n " )
fw ( " * game engine modules \n " )
fw ( " \n " )
fw ( " =================== \n " )
fw ( " Application Modules \n " )
fw ( " =================== \n " )
fw ( " \n " )
fw ( " .. toctree:: \n " )
fw ( " :maxdepth: 1 \n \n " )
if " bpy.context " not in EXCLUDE_MODULES :
fw ( " bpy.context.rst \n \n " ) # note: not actually a module
if " bpy.data " not in EXCLUDE_MODULES :
fw ( " bpy.data.rst \n \n " ) # note: not actually a module
if " bpy.ops " not in EXCLUDE_MODULES :
fw ( " bpy.ops.rst \n \n " )
if " bpy.types " not in EXCLUDE_MODULES :
fw ( " bpy.types.rst \n \n " )
# py modules
if " bpy.utils " not in EXCLUDE_MODULES :
fw ( " bpy.utils.rst \n \n " )
if " bpy.path " not in EXCLUDE_MODULES :
fw ( " bpy.path.rst \n \n " )
if " bpy.app " not in EXCLUDE_MODULES :
fw ( " bpy.app.rst \n \n " )
# C modules
if " bpy.props " not in EXCLUDE_MODULES :
fw ( " bpy.props.rst \n \n " )
fw ( " ================== \n " )
fw ( " Standalone Modules \n " )
fw ( " ================== \n " )
fw ( " \n " )
fw ( " .. toctree:: \n " )
fw ( " :maxdepth: 1 \n \n " )
if " mathutils " not in EXCLUDE_MODULES :
fw ( " mathutils.rst \n \n " )
if " mathutils.geometry " not in EXCLUDE_MODULES :
fw ( " mathutils.geometry.rst \n \n " )
# XXX TODO
#fw(" bgl.rst\n\n")
if " blf " not in EXCLUDE_MODULES :
fw ( " blf.rst \n \n " )
if " aud " not in EXCLUDE_MODULES :
fw ( " aud.rst \n \n " )
# game engine
if " bge " not in EXCLUDE_MODULES :
fw ( " =================== \n " )
fw ( " Game Engine Modules \n " )
fw ( " =================== \n " )
fw ( " \n " )
fw ( " .. toctree:: \n " )
fw ( " :maxdepth: 1 \n \n " )
fw ( " bge.types.rst \n \n " )
fw ( " bge.logic.rst \n \n " )
fw ( " bge.render.rst \n \n " )
fw ( " bge.events.rst \n \n " )
file . close ( )
# internal modules
if " bpy.ops " not in EXCLUDE_MODULES :
filepath = os . path . join ( BASEPATH , " bpy.ops.rst " )
file = open ( filepath , " w " )
fw = file . write
fw ( " Operators (bpy.ops) \n " )
fw ( " =================== \n \n " )
2011-02-18 09:47:37 +01:00
write_example_ref ( " " , fw , " bpy.ops " )
2011-02-16 06:18:10 +01:00
fw ( " .. toctree:: \n " )
fw ( " :glob: \n \n " )
fw ( " bpy.ops.* \n \n " )
file . close ( )
if " bpy.types " not in EXCLUDE_MODULES :
filepath = os . path . join ( BASEPATH , " bpy.types.rst " )
file = open ( filepath , " w " )
fw = file . write
fw ( " Types (bpy.types) \n " )
fw ( " ================= \n \n " )
fw ( " .. toctree:: \n " )
fw ( " :glob: \n \n " )
fw ( " bpy.types.* \n \n " )
file . close ( )
if " bpy.data " not in EXCLUDE_MODULES :
# not actually a module, only write this file so we
# can reference in the TOC
filepath = os . path . join ( BASEPATH , " bpy.data.rst " )
file = open ( filepath , " w " )
fw = file . write
fw ( " Data Access (bpy.data) \n " )
fw ( " ====================== \n \n " )
fw ( " .. module:: bpy \n " )
fw ( " \n " )
fw ( " This module is used for all blender/python access. \n " )
fw ( " \n " )
fw ( " .. data:: data \n " )
fw ( " \n " )
fw ( " Access to blenders internal data \n " )
fw ( " \n " )
fw ( " :type: :class:`bpy.types.BlendData` \n " )
fw ( " \n " )
fw ( " .. literalinclude:: ../examples/bpy.data.py \n " )
file . close ( )
EXAMPLE_SET_USED . add ( " bpy.data " )
module = None
if " bpy.context " not in EXCLUDE_MODULES :
# one of a kind, context doc (uses ctypes to extract info!)
pycontext2sphinx ( BASEPATH )
# python modules
if " bpy.utils " not in EXCLUDE_MODULES :
from bpy import utils as module
pymodule2sphinx ( BASEPATH , " bpy.utils " , module , " Utilities (bpy.utils) " )
if " bpy.path " not in EXCLUDE_MODULES :
from bpy import path as module
pymodule2sphinx ( BASEPATH , " bpy.path " , module , " Path Utilities (bpy.path) " )
# C modules
if " bpy.app " not in EXCLUDE_MODULES :
from bpy import app as module
pymodule2sphinx ( BASEPATH , " bpy.app " , module , " Application Data (bpy.app) " )
if " bpy.props " not in EXCLUDE_MODULES :
from bpy import props as module
pymodule2sphinx ( BASEPATH , " bpy.props " , module , " Property Definitions (bpy.props) " )
if " mathutils " not in EXCLUDE_MODULES :
import mathutils as module
pymodule2sphinx ( BASEPATH , " mathutils " , module , " Math Types & Utilities (mathutils) " )
if " mathutils.geometry " not in EXCLUDE_MODULES :
import mathutils . geometry as module
pymodule2sphinx ( BASEPATH , " mathutils.geometry " , module , " Geometry Utilities (mathutils.geometry) " )
if " mathutils.geometry " not in EXCLUDE_MODULES :
import blf as module
pymodule2sphinx ( BASEPATH , " blf " , module , " Font Drawing (blf) " )
# XXX TODO
#import bgl as module
#pymodule2sphinx(BASEPATH, "bgl", module, "Blender OpenGl wrapper (bgl)")
#del module
if " aud " not in EXCLUDE_MODULES :
import aud as module
pymodule2sphinx ( BASEPATH , " aud " , module , " Audio System (aud) " )
del module
## game engine
import shutil
# copy2 keeps time/date stamps
if " bge " not in EXCLUDE_MODULES :
shutil . copy2 ( os . path . join ( BASEPATH , " .. " , " rst " , " bge.types.rst " ) , BASEPATH )
shutil . copy2 ( os . path . join ( BASEPATH , " .. " , " rst " , " bge.logic.rst " ) , BASEPATH )
shutil . copy2 ( os . path . join ( BASEPATH , " .. " , " rst " , " bge.render.rst " ) , BASEPATH )
shutil . copy2 ( os . path . join ( BASEPATH , " .. " , " rst " , " bge.events.rst " ) , BASEPATH )
if 0 :
filepath = os . path . join ( BASEPATH , " bpy.rst " )
file = open ( filepath , " w " )
fw = file . write
fw ( " \n " )
title = " :mod:`bpy` --- Blender Python Module "
2011-03-22 05:28:51 +01:00
write_title ( fw , title , " = " )
2011-02-16 06:18:10 +01:00
fw ( " .. module:: bpy.types \n \n " )
file . close ( )
# bpy.types and bpy.ops
pyrna2sphinx ( BASEPATH )
2009-12-25 16:50:53 +01:00
file . close ( )
2011-02-04 10:27:25 +01:00
2010-07-19 15:36:10 +02:00
def main ( ) :
import bpy
2009-12-25 16:50:53 +01:00
if ' bpy ' not in dir ( ) :
print ( " \n Error, this script must run from inside blender2.5 " )
print ( script_help_msg )
else :
2010-01-31 22:52:26 +01:00
import shutil
2010-10-13 12:42:33 +02:00
script_dir = os . path . dirname ( __file__ )
2011-02-04 10:27:25 +01:00
path_in = os . path . join ( script_dir , " sphinx-in " )
path_out = os . path . join ( script_dir , " sphinx-out " )
path_examples = os . path . join ( script_dir , " examples " )
2010-05-03 17:52:15 +02:00
# only for partial updates
path_in_tmp = path_in + " -tmp "
2010-01-31 22:52:26 +01:00
2010-05-09 19:18:57 +02:00
if not os . path . exists ( path_in ) :
os . mkdir ( path_in )
2010-02-28 14:45:08 +01:00
for f in os . listdir ( path_examples ) :
if f . endswith ( " .py " ) :
EXAMPLE_SET . add ( os . path . splitext ( f ) [ 0 ] )
2010-01-31 22:52:26 +01:00
2010-05-03 17:52:15 +02:00
# only for full updates
if _BPY_FULL_REBUILD :
shutil . rmtree ( path_in , True )
shutil . rmtree ( path_out , True )
else :
# write here, then move
shutil . rmtree ( path_in_tmp , True )
rna2sphinx ( path_in_tmp )
if not _BPY_FULL_REBUILD :
import filecmp
# now move changed files from 'path_in_tmp' --> 'path_in'
file_list_path_in = set ( os . listdir ( path_in ) )
file_list_path_in_tmp = set ( os . listdir ( path_in_tmp ) )
2011-02-04 10:27:25 +01:00
2010-05-03 17:52:15 +02:00
# remove deprecated files that have been removed.
for f in sorted ( file_list_path_in ) :
if f not in file_list_path_in_tmp :
print ( " \t deprecated: %s " % f )
os . remove ( os . path . join ( path_in , f ) )
# freshen with new files.
for f in sorted ( file_list_path_in_tmp ) :
f_from = os . path . join ( path_in_tmp , f )
f_to = os . path . join ( path_in , f )
do_copy = True
if f in file_list_path_in :
if filecmp . cmp ( f_from , f_to ) :
do_copy = False
2011-02-04 10:27:25 +01:00
2010-05-03 17:52:15 +02:00
if do_copy :
print ( " \t updating: %s " % f )
shutil . copy ( f_from , f_to )
''' else:
print ( " \t keeping: %s " % f ) # eh, not that useful'''
2010-02-28 14:45:08 +01:00
EXAMPLE_SET_UNUSED = EXAMPLE_SET - EXAMPLE_SET_USED
if EXAMPLE_SET_UNUSED :
print ( " \n Unused examples found in ' %s ' ... " % path_examples )
for f in EXAMPLE_SET_UNUSED :
print ( " %s .py " % f )
print ( " %d total \n " % len ( EXAMPLE_SET_UNUSED ) )
2009-12-25 16:50:53 +01:00
import sys
sys . exit ( )
2010-07-19 15:36:10 +02:00
if __name__ == ' __main__ ' :
main ( )