2009-12-25 15:50:53 +00: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 13:34:04 +00:00
|
|
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2009-12-25 15:50:53 +00:00
|
|
|
#
|
|
|
|
# Contributor(s): Campbell Barton
|
|
|
|
#
|
|
|
|
# #**** END GPL LICENSE BLOCK #****
|
|
|
|
|
2011-02-04 09:27:25 +00:00
|
|
|
# <pep8 compliant>
|
|
|
|
|
2009-12-25 15:50:53 +00:00
|
|
|
script_help_msg = '''
|
2010-10-13 10:42:33 +00:00
|
|
|
Usage:
|
2009-12-25 15:50:53 +00:00
|
|
|
|
2010-10-13 10:42:33 +00:00
|
|
|
For HTML generation
|
|
|
|
-------------------
|
|
|
|
- Run this script from blenders root path once you have compiled blender
|
|
|
|
|
2011-03-31 12:45:54 +00:00
|
|
|
./blender.bin --background --python doc/python_api/sphinx_doc_gen.py
|
2010-01-28 10:48:17 +00:00
|
|
|
|
2011-06-27 04:50:08 +00:00
|
|
|
This will generate python files in doc/python_api/sphinx-in/
|
|
|
|
providing ./blender.bin is or links to the blender executable
|
2010-01-28 10:48:17 +00:00
|
|
|
|
2010-10-13 10:42:33 +00:00
|
|
|
- Generate html docs by running...
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2011-05-28 07:47:58 +00:00
|
|
|
cd doc/python_api
|
|
|
|
sphinx-build sphinx-in sphinx-out
|
2010-10-13 10:42:33 +00:00
|
|
|
|
2011-06-27 04:50:08 +00:00
|
|
|
This requires sphinx 1.0.7 to be installed.
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2010-01-28 10:48:17 +00:00
|
|
|
For PDF generation
|
2010-10-13 10:42:33 +00:00
|
|
|
------------------
|
|
|
|
- After you have built doc/python_api/sphinx-in (see above), run:
|
2010-01-28 10:48:17 +00:00
|
|
|
|
2010-10-13 10:42:33 +00:00
|
|
|
sphinx-build -b latex doc/python_api/sphinx-in doc/python_api/sphinx-out
|
|
|
|
cd doc/python_api/sphinx-out
|
2010-01-28 10:48:17 +00:00
|
|
|
make
|
2009-12-25 15:50:53 +00:00
|
|
|
'''
|
|
|
|
|
2011-06-27 04:50:08 +00:00
|
|
|
# Check we're running in blender
|
|
|
|
if __import__("sys").modules.get("bpy") is None:
|
|
|
|
print("\nError, this script must run from inside blender2.5")
|
|
|
|
print(script_help_msg)
|
|
|
|
|
|
|
|
import sys
|
|
|
|
sys.exit()
|
|
|
|
|
|
|
|
|
2011-02-16 05:18:10 +00:00
|
|
|
# Switch for quick testing
|
|
|
|
if 1:
|
|
|
|
# full build
|
2011-08-25 04:25:33 +00:00
|
|
|
EXCLUDE_INFO_DOCS = False
|
2011-02-16 05:18:10 +00:00
|
|
|
EXCLUDE_MODULES = ()
|
|
|
|
FILTER_BPY_TYPES = None
|
|
|
|
FILTER_BPY_OPS = None
|
|
|
|
|
|
|
|
else:
|
2011-08-25 04:25:33 +00:00
|
|
|
EXCLUDE_INFO_DOCS = False
|
2011-02-16 05:18:10 +00:00
|
|
|
# for testing so doc-builds dont take so long.
|
|
|
|
EXCLUDE_MODULES = (
|
2011-07-01 11:16:42 +00:00
|
|
|
"bpy.context",
|
2011-02-16 05:18:10 +00:00
|
|
|
"bpy.app",
|
|
|
|
"bpy.path",
|
|
|
|
"bpy.data",
|
2011-03-22 04:28:51 +00:00
|
|
|
"bpy.props",
|
2011-02-16 05:18:10 +00:00
|
|
|
"bpy.utils",
|
2011-02-18 08:47:37 +00:00
|
|
|
"bpy.context",
|
2011-09-15 16:15:24 +00:00
|
|
|
# "bpy.types", # supports filtering
|
2011-02-16 05:18:10 +00:00
|
|
|
"bpy.ops", # supports filtering
|
2011-07-01 11:16:42 +00:00
|
|
|
"bpy_extras",
|
2011-08-23 11:28:18 +00:00
|
|
|
"bge",
|
2011-02-16 05:18:10 +00:00
|
|
|
"aud",
|
2011-07-07 19:23:51 +00:00
|
|
|
"bgl",
|
2011-02-16 05:18:10 +00:00
|
|
|
"blf",
|
|
|
|
"mathutils",
|
|
|
|
"mathutils.geometry",
|
|
|
|
)
|
|
|
|
|
2011-09-15 16:15:24 +00:00
|
|
|
FILTER_BPY_TYPES = ("bpy_struct", "Operator", "ID") # allow
|
2011-02-18 08:47:37 +00:00
|
|
|
FILTER_BPY_OPS = ("import.scene", ) # allow
|
2011-02-16 05:18:10 +00: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
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
2011-08-25 04:25:33 +00:00
|
|
|
# extra info, not api reference docs
|
|
|
|
# stored in ./rst/info/
|
|
|
|
INFO_DOCS = (
|
|
|
|
("info_quickstart.rst", "Blender/Python Quickstart: new to blender/scripting and want to get you're feet wet?"),
|
|
|
|
("info_overview.rst", "Blender/Python API Overview: a more complete explanation of python integration"),
|
2011-09-08 23:59:47 +00:00
|
|
|
("info_best_practice.rst", "Best Practice: Conventions to follow for writing good scripts"),
|
2011-09-08 01:26:23 +00:00
|
|
|
("info_tips_and_tricks.rst", "Tips and Tricks: Hints to help you while writeing scripts for blender"),
|
2011-08-26 04:00:55 +00:00
|
|
|
("info_gotcha.rst", "Gotcha's: some of the problems you may come up against when writing scripts"),
|
2011-08-25 04:25:33 +00:00
|
|
|
)
|
2011-02-16 05:18:10 +00:00
|
|
|
|
2010-05-30 00:24:32 +00: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 09:44:04 +00:00
|
|
|
|
2009-12-25 15:50:53 +00:00
|
|
|
import os
|
2009-12-26 16:47:25 +00:00
|
|
|
import inspect
|
2009-12-25 15:50:53 +00:00
|
|
|
import bpy
|
|
|
|
import rna_info
|
|
|
|
|
2010-04-05 22:37:09 +00:00
|
|
|
# lame, python wont give some access
|
2010-08-11 17:13:39 +00:00
|
|
|
ClassMethodDescriptorType = type(dict.__dict__['fromkeys'])
|
2010-04-05 22:37:09 +00:00
|
|
|
MethodDescriptorType = type(dict.get)
|
|
|
|
GetSetDescriptorType = type(int.real)
|
|
|
|
|
2010-02-28 13:45:08 +00:00
|
|
|
EXAMPLE_SET = set()
|
|
|
|
EXAMPLE_SET_USED = set()
|
|
|
|
|
2010-04-10 18:35:50 +00:00
|
|
|
_BPY_STRUCT_FAKE = "bpy_struct"
|
2011-03-22 04:28:51 +00:00
|
|
|
_BPY_PROP_COLLECTION_FAKE = "bpy_prop_collection"
|
2010-05-03 15:52:15 +00:00
|
|
|
_BPY_FULL_REBUILD = False
|
2010-04-10 18:35:50 +00:00
|
|
|
|
2011-03-22 04:28:51 +00: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 00:20:32 +00:00
|
|
|
|
2011-03-27 05:23:14 +00:00
|
|
|
|
2010-06-15 02:06:01 +00:00
|
|
|
def undocumented_message(module_name, type_name, identifier):
|
2010-12-10 00:20:32 +00: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 02:06:01 +00:00
|
|
|
return message
|
|
|
|
|
2010-06-11 22:41:13 +00:00
|
|
|
|
2009-12-25 15:50:53 +00:00
|
|
|
def range_str(val):
|
2010-06-15 02:06:01 +00:00
|
|
|
'''
|
|
|
|
Converts values to strings for the range directive.
|
|
|
|
(unused function it seems)
|
|
|
|
'''
|
2011-02-04 09:27:25 +00:00
|
|
|
if val < -10000000:
|
|
|
|
return '-inf'
|
|
|
|
elif val > 10000000:
|
|
|
|
return 'inf'
|
|
|
|
elif type(val) == float:
|
|
|
|
return '%g' % val
|
2009-12-25 15:50:53 +00:00
|
|
|
else:
|
|
|
|
return str(val)
|
|
|
|
|
2010-02-28 13:45:08 +00:00
|
|
|
|
2011-02-16 17:31:04 +00: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 04:28:51 +00:00
|
|
|
def write_title(fw, text, heading_char):
|
|
|
|
fw("%s\n%s\n\n" % (text, len(text) * heading_char))
|
|
|
|
|
|
|
|
|
2010-06-15 02:06:01 +00:00
|
|
|
def write_example_ref(ident, fw, example_id, ext="py"):
|
2010-02-28 13:45:08 +00:00
|
|
|
if example_id in EXAMPLE_SET:
|
2011-02-18 08:47:37 +00:00
|
|
|
|
2011-02-16 17:31:04 +00: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 08:47:37 +00:00
|
|
|
|
2011-02-16 17:31:04 +00:00
|
|
|
text, line_no = example_extract_docstring(filepath_full)
|
2011-02-18 08:47:37 +00:00
|
|
|
|
2011-02-16 17:31:04 +00: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 08:47:37 +00:00
|
|
|
if line_no > 0:
|
|
|
|
fw("%s :lines: %d-\n" % (ident, line_no))
|
2011-02-16 17:31:04 +00:00
|
|
|
fw("\n")
|
2010-02-28 13:45:08 +00:00
|
|
|
EXAMPLE_SET_USED.add(example_id)
|
|
|
|
else:
|
|
|
|
if bpy.app.debug:
|
|
|
|
print("\tskipping example:", example_id)
|
|
|
|
|
2011-02-16 17:31:04 +00: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 13:45:08 +00:00
|
|
|
|
2010-01-31 21:52:26 +00:00
|
|
|
def write_indented_lines(ident, fn, text, strip=True):
|
2010-06-15 02:06:01 +00:00
|
|
|
'''
|
|
|
|
Apply same indentation to all lines in a multilines text.
|
|
|
|
'''
|
2009-12-25 15:50:53 +00:00
|
|
|
if text is None:
|
|
|
|
return
|
2011-05-28 07:47:58 +00:00
|
|
|
|
|
|
|
lines = text.split("\n")
|
|
|
|
|
|
|
|
# strip empty lines from the start/end
|
|
|
|
while lines and not lines[0].strip():
|
|
|
|
del lines[0]
|
|
|
|
while lines and not lines[-1].strip():
|
|
|
|
del lines[-1]
|
|
|
|
|
|
|
|
if strip:
|
|
|
|
ident_strip = 1000
|
|
|
|
for l in lines:
|
|
|
|
if l.strip():
|
|
|
|
ident_strip = min(ident_strip, len(l) - len(l.lstrip()))
|
|
|
|
for l in lines:
|
|
|
|
fn(ident + l[ident_strip:] + "\n")
|
|
|
|
else:
|
|
|
|
for l in lines:
|
2010-01-31 21:52:26 +00:00
|
|
|
fn(ident + l + "\n")
|
2009-12-25 15:50:53 +00:00
|
|
|
|
2010-01-22 02:04:25 +00: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 09:27:25 +00:00
|
|
|
|
2010-01-22 02:04:25 +00: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__:
|
2011-05-28 07:47:58 +00:00
|
|
|
write_indented_lines(ident + " ", fw, py_func.__doc__)
|
2010-01-22 02:04:25 +00:00
|
|
|
fw("\n")
|
|
|
|
|
2010-04-10 18:35:50 +00:00
|
|
|
|
2011-02-04 09:27:25 +00:00
|
|
|
def py_descr2sphinx(ident, fw, descr, module_name, type_name, identifier):
|
2010-07-19 13:36:10 +00:00
|
|
|
if identifier.startswith("_"):
|
|
|
|
return
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2010-04-10 18:35:50 +00:00
|
|
|
doc = descr.__doc__
|
|
|
|
if not doc:
|
2010-06-15 02:06:01 +00:00
|
|
|
doc = undocumented_message(module_name, type_name, identifier)
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2010-04-10 18:35:50 +00:00
|
|
|
if type(descr) == GetSetDescriptorType:
|
|
|
|
fw(ident + ".. attribute:: %s\n\n" % identifier)
|
2010-05-30 00:24:32 +00:00
|
|
|
write_indented_lines(ident + " ", fw, doc, False)
|
2011-05-28 07:47:58 +00:00
|
|
|
fw("\n")
|
2010-08-11 17:13:39 +00:00
|
|
|
elif type(descr) in (MethodDescriptorType, ClassMethodDescriptorType):
|
2010-04-10 18:35:50 +00:00
|
|
|
write_indented_lines(ident, fw, doc, False)
|
2011-05-28 07:47:58 +00:00
|
|
|
fw("\n")
|
2010-04-10 18:35:50 +00:00
|
|
|
else:
|
2010-08-11 17:13:39 +00:00
|
|
|
raise TypeError("type was not GetSetDescriptorType, MethodDescriptorType or ClassMethodDescriptorType")
|
2010-04-10 18:35:50 +00:00
|
|
|
|
2011-03-31 12:45:54 +00:00
|
|
|
write_example_ref(ident + " ", fw, module_name + "." + type_name + "." + identifier)
|
2010-04-10 18:35:50 +00:00
|
|
|
fw("\n")
|
|
|
|
|
2010-06-15 02:06:01 +00:00
|
|
|
|
|
|
|
def py_c_func2sphinx(ident, fw, module_name, type_name, identifier, py_func, is_class=True):
|
2010-01-22 02:04:25 +00:00
|
|
|
'''
|
|
|
|
c defined function to sphinx.
|
|
|
|
'''
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2010-01-22 02:04:25 +00:00
|
|
|
# dump the docstring, assume its formatted correctly
|
|
|
|
if py_func.__doc__:
|
2010-01-31 21:52:26 +00:00
|
|
|
write_indented_lines(ident, fw, py_func.__doc__, False)
|
2010-01-22 02:04:25 +00:00
|
|
|
fw("\n")
|
|
|
|
else:
|
|
|
|
fw(ident + ".. function:: %s()\n\n" % identifier)
|
2010-06-15 02:06:01 +00:00
|
|
|
fw(ident + " " + undocumented_message(module_name, type_name, identifier))
|
|
|
|
|
2011-03-14 10:31:50 +00: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 02:04:25 +00:00
|
|
|
|
|
|
|
def pyprop2sphinx(ident, fw, identifier, py_prop):
|
|
|
|
'''
|
|
|
|
python property to sphinx
|
|
|
|
'''
|
2010-06-28 00:06:23 +00: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 02:04:25 +00: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 19:06:18 +00:00
|
|
|
attribute_set = set()
|
2010-01-22 02:04:25 +00:00
|
|
|
filepath = os.path.join(BASEPATH, module_name + ".rst")
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2011-05-28 07:47:58 +00:00
|
|
|
module_all = getattr(module, "__all__", None)
|
|
|
|
module_dir = sorted(dir(module))
|
|
|
|
|
|
|
|
if module_all:
|
|
|
|
module_dir = module_all
|
|
|
|
|
2010-01-22 02:04:25 +00:00
|
|
|
file = open(filepath, "w")
|
2010-01-27 21:33:39 +00:00
|
|
|
|
2010-01-22 02:04:25 +00:00
|
|
|
fw = file.write
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2011-05-28 07:47:58 +00:00
|
|
|
write_title(fw, "%s (%s)" % (title, module_name), "=")
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2010-01-22 02:04:25 +00:00
|
|
|
fw(".. module:: %s\n\n" % module_name)
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2010-01-22 02:04:25 +00:00
|
|
|
if module.__doc__:
|
|
|
|
# Note, may contain sphinx syntax, dont mangle!
|
|
|
|
fw(module.__doc__.strip())
|
|
|
|
fw("\n\n")
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2010-02-28 13:45:08 +00:00
|
|
|
write_example_ref("", fw, module_name)
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2011-05-28 07:47:58 +00:00
|
|
|
# write submodules
|
|
|
|
# we could also scan files but this ensures __all__ is used correctly
|
|
|
|
if module_all is not None:
|
|
|
|
submod_name = None
|
|
|
|
submod = None
|
|
|
|
submod_ls = []
|
|
|
|
for submod_name in module_all:
|
|
|
|
ns = {}
|
|
|
|
exec_str = "from %s import %s as submod" % (module.__name__, submod_name)
|
|
|
|
exec(exec_str, ns, ns)
|
|
|
|
submod = ns["submod"]
|
|
|
|
if type(submod) == types.ModuleType:
|
|
|
|
submod_ls.append((submod_name, submod))
|
|
|
|
|
|
|
|
del submod_name
|
|
|
|
del submod
|
|
|
|
|
|
|
|
if submod_ls:
|
|
|
|
fw(".. toctree::\n")
|
|
|
|
fw(" :maxdepth: 1\n\n")
|
|
|
|
|
|
|
|
for submod_name, submod in submod_ls:
|
|
|
|
submod_name_full = "%s.%s" % (module_name, submod_name)
|
|
|
|
fw(" %s.rst\n\n" % submod_name_full)
|
|
|
|
|
|
|
|
pymodule2sphinx(BASEPATH, submod_name_full, submod, "%s submodule" % module_name)
|
|
|
|
del submod_ls
|
|
|
|
# done writing submodules!
|
|
|
|
|
2010-01-31 21:52:26 +00:00
|
|
|
# write members of the module
|
|
|
|
# only tested with PyStructs which are not exactly modules
|
2010-04-10 18:35:50 +00:00
|
|
|
for key, descr in sorted(type(module).__dict__.items()):
|
2010-12-06 12:36:55 +00: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 09:27:25 +00:00
|
|
|
if type(descr) == types.GetSetDescriptorType: # 'bpy_app_type' name is only used for examples and messages
|
2010-12-06 12:36:55 +00: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 21:52:26 +00:00
|
|
|
if type(descr) == types.MemberDescriptorType:
|
|
|
|
if descr.__doc__:
|
2010-04-10 18:35:50 +00:00
|
|
|
fw(".. data:: %s\n\n" % key)
|
2010-01-31 21:52:26 +00:00
|
|
|
write_indented_lines(" ", fw, descr.__doc__, False)
|
|
|
|
fw("\n")
|
2011-05-28 07:47:58 +00:00
|
|
|
attribute_set.add(key)
|
|
|
|
|
2010-04-10 19:06:18 +00:00
|
|
|
del key, descr
|
2011-02-04 09:27:25 +00: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 09:44:04 +00:00
|
|
|
classes = []
|
2011-07-31 03:15:37 +00:00
|
|
|
submodules = []
|
2010-01-22 02:04:25 +00:00
|
|
|
|
2011-05-28 07:47:58 +00:00
|
|
|
for attribute in module_dir:
|
2010-01-22 02:04:25 +00:00
|
|
|
if not attribute.startswith("_"):
|
2010-04-10 19:06:18 +00:00
|
|
|
if attribute in attribute_set:
|
|
|
|
continue
|
|
|
|
|
2011-02-04 09:27:25 +00:00
|
|
|
if attribute.startswith("n_"): # annoying exception, needed for bpy.app
|
2010-04-10 19:06:18 +00:00
|
|
|
continue
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2010-01-22 02:04:25 +00: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 09:44:04 +00:00
|
|
|
|
2010-01-22 02:04:25 +00:00
|
|
|
if value_type == types.FunctionType:
|
|
|
|
pyfunc2sphinx("", fw, attribute, value, is_class=False)
|
2011-02-04 09:27:25 +00:00
|
|
|
elif value_type in (types.BuiltinMethodType, types.BuiltinFunctionType): # both the same at the moment but to be future proof
|
2010-01-22 02:04:25 +00: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 10:31:50 +00: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 09:44:04 +00:00
|
|
|
elif value_type == type:
|
|
|
|
classes.append((attribute, value))
|
2011-07-31 03:15:37 +00:00
|
|
|
elif issubclass(value_type, types.ModuleType):
|
|
|
|
submodules.append((attribute, value))
|
2010-04-05 22:37:09 +00: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:
|
2011-07-31 03:15:37 +00:00
|
|
|
print("\tnot documenting %s.%s of %r type" % (module_name, attribute, value_type.__name__))
|
2010-04-10 19:06:18 +00:00
|
|
|
continue
|
|
|
|
|
|
|
|
attribute_set.add(attribute)
|
2010-01-22 02:04:25 +00:00
|
|
|
# TODO, more types...
|
2010-04-10 18:35:50 +00:00
|
|
|
|
2011-07-31 03:15:37 +00:00
|
|
|
# TODO, bpy_extras does this already, mathutils not.
|
|
|
|
"""
|
|
|
|
if submodules:
|
|
|
|
fw("\n"
|
|
|
|
"**********\n"
|
|
|
|
"Submodules\n"
|
|
|
|
"**********\n"
|
|
|
|
"\n"
|
|
|
|
)
|
|
|
|
for attribute, submod in submodules:
|
|
|
|
fw("* :mod:`%s.%s`\n" % (module_name, attribute))
|
|
|
|
fw("\n")
|
|
|
|
"""
|
|
|
|
|
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 09:44:04 +00:00
|
|
|
# write collected classes now
|
2010-04-10 18:35:50 +00: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 09:44:04 +00:00
|
|
|
# May need to be its own function
|
2010-04-10 18:35:50 +00: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 09:44:04 +00:00
|
|
|
if value.__doc__:
|
2010-01-31 21:52:26 +00:00
|
|
|
write_indented_lines(" ", fw, value.__doc__, False)
|
2010-01-27 21:33:39 +00:00
|
|
|
fw("\n")
|
2010-04-10 18:35:50 +00: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 09:44:04 +00:00
|
|
|
|
2010-04-10 18:35:50 +00:00
|
|
|
descr_items = [(key, descr) for key, descr in sorted(value.__dict__.items()) if not key.startswith("__")]
|
|
|
|
|
2010-08-11 17:13:39 +00:00
|
|
|
for key, descr in descr_items:
|
2010-08-11 22:36:43 +00:00
|
|
|
if type(descr) == ClassMethodDescriptorType:
|
2010-08-11 17:13:39 +00:00
|
|
|
py_descr2sphinx(" ", fw, descr, module_name, type_name, key)
|
|
|
|
|
2010-04-10 18:35:50 +00:00
|
|
|
for key, descr in descr_items:
|
2010-08-11 22:36:43 +00:00
|
|
|
if type(descr) == MethodDescriptorType:
|
2010-04-10 18:35:50 +00: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 09:44:04 +00:00
|
|
|
fw("\n\n")
|
2010-01-22 02:04:25 +00:00
|
|
|
|
|
|
|
file.close()
|
|
|
|
|
|
|
|
|
2011-02-15 15:37:40 +00: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),
|
2011-04-01 04:22:30 +00:00
|
|
|
"image_paint_object": ("Object", False),
|
2011-02-15 15:37:40 +00:00
|
|
|
"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),
|
2011-09-06 00:12:34 +00:00
|
|
|
"speaker": ("Speaker", False),
|
2011-02-15 15:37:40 +00:00
|
|
|
"texture": ("Texture", 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 02:25:03 +00:00
|
|
|
pass # will have raised an error above
|
2011-02-15 15:37:40 +00:00
|
|
|
|
2011-02-22 05:23:20 +00:00
|
|
|
file.close()
|
|
|
|
|
2011-02-15 15:37:40 +00:00
|
|
|
|
2011-09-16 02:42:50 +00:00
|
|
|
def pyrna_enum2sphinx(prop, use_empty_descriptions=False):
|
2011-09-15 16:15:24 +00:00
|
|
|
""" write a bullet point list of enum + descrptons
|
|
|
|
"""
|
|
|
|
|
|
|
|
if use_empty_descriptions:
|
|
|
|
ok = True
|
|
|
|
else:
|
|
|
|
ok = False
|
|
|
|
for identifier, name, description in prop.enum_items:
|
|
|
|
if description:
|
|
|
|
ok = True
|
|
|
|
break
|
|
|
|
|
|
|
|
if ok:
|
|
|
|
return "".join(["* ``%s`` %s.\n" %
|
|
|
|
(identifier,
|
|
|
|
", ".join(val for val in (name, description) if val),
|
|
|
|
)
|
|
|
|
for identifier, name, description in prop.enum_items
|
|
|
|
])
|
|
|
|
else:
|
|
|
|
return ""
|
|
|
|
|
|
|
|
|
2011-02-16 05:18:10 +00:00
|
|
|
def pyrna2sphinx(BASEPATH):
|
|
|
|
""" bpy.types and bpy.ops
|
|
|
|
"""
|
2009-12-25 15:50:53 +00:00
|
|
|
structs, funcs, ops, props = rna_info.BuildRNAInfo()
|
2011-02-16 05:18:10 +00: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 15:50:53 +00:00
|
|
|
|
2011-02-16 05:18:10 +00: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 15:50:53 +00:00
|
|
|
|
2009-12-26 16:47:25 +00:00
|
|
|
def write_param(ident, fw, prop, is_return=False):
|
|
|
|
if is_return:
|
|
|
|
id_name = "return"
|
|
|
|
id_type = "rtype"
|
2011-03-22 04:28:51 +00:00
|
|
|
kwargs = {"as_ret": True}
|
2010-01-18 10:45:54 +00:00
|
|
|
identifier = ""
|
2009-12-25 15:50:53 +00:00
|
|
|
else:
|
2009-12-26 16:47:25 +00:00
|
|
|
id_name = "arg"
|
|
|
|
id_type = "type"
|
2011-03-22 04:28:51 +00:00
|
|
|
kwargs = {"as_arg": True}
|
2010-01-18 10:45:54 +00:00
|
|
|
identifier = " %s" % prop.identifier
|
2009-12-25 15:50:53 +00:00
|
|
|
|
2011-03-22 04:28:51 +00:00
|
|
|
kwargs["class_fmt"] = ":class:`%s`"
|
|
|
|
|
|
|
|
kwargs["collection_id"] = _BPY_PROP_COLLECTION_ID
|
|
|
|
|
2010-01-18 10:45:54 +00:00
|
|
|
type_descr = prop.get_type_description(**kwargs)
|
2011-09-15 16:15:24 +00:00
|
|
|
|
|
|
|
enum_text = pyrna_enum2sphinx(prop)
|
|
|
|
|
|
|
|
if prop.name or prop.description or enum_text:
|
|
|
|
fw(ident + ":%s%s:\n\n" % (id_name, identifier))
|
|
|
|
|
|
|
|
if prop.name or prop.description:
|
|
|
|
fw(ident + " " + ", ".join(val for val in (prop.name, prop.description) if val) + "\n\n")
|
|
|
|
|
|
|
|
# special exception, cant use genric code here for enums
|
|
|
|
if enum_text:
|
|
|
|
write_indented_lines(ident + " ", fw, enum_text)
|
|
|
|
fw("\n")
|
|
|
|
del enum_text
|
|
|
|
# end enum exception
|
|
|
|
|
2010-01-18 10:45:54 +00:00
|
|
|
fw(ident + ":%s%s: %s\n" % (id_type, identifier, type_descr))
|
2009-12-25 15:50:53 +00:00
|
|
|
|
|
|
|
def write_struct(struct):
|
|
|
|
#if not struct.identifier.startswith("Sc") and not struct.identifier.startswith("I"):
|
|
|
|
# return
|
|
|
|
|
2010-01-02 19:01:19 +00:00
|
|
|
#if not struct.identifier == "Object":
|
|
|
|
# return
|
2009-12-25 15:50:53 +00:00
|
|
|
|
|
|
|
filepath = os.path.join(BASEPATH, "bpy.types.%s.rst" % struct.identifier)
|
|
|
|
file = open(filepath, "w")
|
|
|
|
fw = file.write
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2010-04-10 18:35:50 +00: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 15:50:53 +00:00
|
|
|
else:
|
|
|
|
title = struct.identifier
|
|
|
|
|
2011-03-22 04:28:51 +00:00
|
|
|
write_title(fw, title, "=")
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2009-12-25 15:50:53 +00:00
|
|
|
fw(".. module:: bpy.types\n\n")
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2011-02-18 08:47:37 +00:00
|
|
|
# docs first?, ok
|
2011-02-16 17:31:04 +00:00
|
|
|
write_example_ref("", fw, "bpy.types.%s" % struct.identifier)
|
|
|
|
|
2010-04-10 18:35:50 +00: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 09:27:25 +00:00
|
|
|
|
2010-04-10 18:35:50 +00:00
|
|
|
if base_ids:
|
|
|
|
if len(base_ids) > 1:
|
2009-12-25 15:50:53 +00:00
|
|
|
fw("base classes --- ")
|
|
|
|
else:
|
|
|
|
fw("base class --- ")
|
|
|
|
|
2010-09-19 07:07:14 +00:00
|
|
|
fw(", ".join((":class:`%s`" % base_id) for base_id in base_ids))
|
2009-12-25 15:50:53 +00:00
|
|
|
fw("\n\n")
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2010-04-10 18:35:50 +00: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 07:07:14 +00:00
|
|
|
fw("subclasses --- \n" + ", ".join((":class:`%s`" % s) for s in subclass_ids) + "\n\n")
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2010-04-10 18:35:50 +00:00
|
|
|
base_id = getattr(struct.base, "identifier", "")
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2010-04-10 18:35:50 +00:00
|
|
|
if _BPY_STRUCT_FAKE:
|
|
|
|
if not base_id:
|
|
|
|
base_id = _BPY_STRUCT_FAKE
|
2009-12-25 15:50:53 +00:00
|
|
|
|
2010-04-10 18:35:50 +00:00
|
|
|
if base_id:
|
|
|
|
fw(".. class:: %s(%s)\n\n" % (struct.identifier, base_id))
|
2009-12-25 15:50:53 +00:00
|
|
|
else:
|
|
|
|
fw(".. class:: %s\n\n" % struct.identifier)
|
|
|
|
|
|
|
|
fw(" %s\n\n" % struct.description)
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2010-06-28 00:06:23 +00:00
|
|
|
# properties sorted in alphabetical order
|
2010-07-15 11:51:43 +00:00
|
|
|
sorted_struct_properties = struct.properties[:]
|
|
|
|
sorted_struct_properties.sort(key=lambda prop: prop.identifier)
|
|
|
|
|
2010-06-28 00:06:23 +00:00
|
|
|
for prop in sorted_struct_properties:
|
2011-03-22 04:28:51 +00:00
|
|
|
type_descr = prop.get_type_description(class_fmt=":class:`%s`", collection_id=_BPY_PROP_COLLECTION_ID)
|
2010-06-28 00:06:23 +00: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 16:47:25 +00:00
|
|
|
if prop.description:
|
|
|
|
fw(" %s\n\n" % prop.description)
|
2011-09-15 16:15:24 +00:00
|
|
|
|
|
|
|
# special exception, cant use genric code here for enums
|
|
|
|
if prop.type == "enum":
|
|
|
|
enum_text = pyrna_enum2sphinx(prop)
|
|
|
|
if enum_text:
|
|
|
|
write_indented_lines(" ", fw, enum_text)
|
|
|
|
fw("\n")
|
|
|
|
del enum_text
|
|
|
|
# end enum exception
|
|
|
|
|
2010-06-02 21:28:17 +00:00
|
|
|
fw(" :type: %s\n\n" % type_descr)
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2009-12-25 15:50:53 +00:00
|
|
|
# python attributes
|
|
|
|
py_properties = struct.get_py_properties()
|
|
|
|
py_prop = None
|
|
|
|
for identifier, py_prop in py_properties:
|
2010-01-22 02:04:25 +00:00
|
|
|
pyprop2sphinx(" ", fw, identifier, py_prop)
|
2009-12-25 15:50:53 +00:00
|
|
|
del py_properties, py_prop
|
|
|
|
|
|
|
|
for func in struct.functions:
|
2010-09-19 07:07:14 +00:00
|
|
|
args_str = ", ".join(prop.get_arg_default(force=False) for prop in func.args)
|
2009-12-25 15:50:53 +00:00
|
|
|
|
2010-08-17 14:32:14 +00:00
|
|
|
fw(" .. %s:: %s(%s)\n\n" % ("classmethod" if func.is_classmethod else "method", func.identifier, args_str))
|
2009-12-25 15:50:53 +00:00
|
|
|
fw(" %s\n\n" % func.description)
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2009-12-25 15:50:53 +00:00
|
|
|
for prop in func.args:
|
2009-12-26 16:47:25 +00:00
|
|
|
write_param(" ", fw, prop)
|
|
|
|
|
2010-01-02 18:55:07 +00:00
|
|
|
if len(func.return_values) == 1:
|
|
|
|
write_param(" ", fw, func.return_values[0], is_return=True)
|
2011-02-04 09:27:25 +00:00
|
|
|
elif func.return_values: # multiple return values
|
2010-09-19 07:07:14 +00:00
|
|
|
fw(" :return (%s):\n" % ", ".join(prop.identifier for prop in func.return_values))
|
2010-01-02 18:55:07 +00:00
|
|
|
for prop in func.return_values:
|
2011-09-15 16:15:24 +00:00
|
|
|
# TODO, pyrna_enum2sphinx for multiple return values... actually dont think we even use this but still!!!
|
2011-03-22 04:28:51 +00:00
|
|
|
type_descr = prop.get_type_description(as_ret=True, class_fmt=":class:`%s`", collection_id=_BPY_PROP_COLLECTION_ID)
|
2010-01-02 18:55:07 +00:00
|
|
|
descr = prop.description
|
|
|
|
if not descr:
|
|
|
|
descr = prop.name
|
2010-01-17 20:59:35 +00:00
|
|
|
fw(" `%s`, %s, %s\n\n" % (prop.identifier, descr, type_descr))
|
2010-01-02 18:55:07 +00:00
|
|
|
|
2011-08-23 11:28:18 +00:00
|
|
|
write_example_ref(" ", fw, "bpy.types." + struct.identifier + "." + func.identifier)
|
|
|
|
|
2009-12-26 16:47:25 +00:00
|
|
|
fw("\n")
|
2009-12-25 15:50:53 +00:00
|
|
|
|
|
|
|
# python methods
|
|
|
|
py_funcs = struct.get_py_functions()
|
|
|
|
py_func = None
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2009-12-25 15:50:53 +00:00
|
|
|
for identifier, py_func in py_funcs:
|
2010-01-22 02:04:25 +00:00
|
|
|
pyfunc2sphinx(" ", fw, identifier, py_func, is_class=True)
|
2009-12-25 15:50:53 +00:00
|
|
|
del py_funcs, py_func
|
|
|
|
|
2011-03-14 10:31:50 +00: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 20:43:58 +00:00
|
|
|
lines = []
|
|
|
|
|
2010-04-10 18:35:50 +00:00
|
|
|
if struct.base or _BPY_STRUCT_FAKE:
|
2010-04-09 20:43:58 +00:00
|
|
|
bases = list(reversed(struct.get_bases()))
|
2010-04-10 18:35:50 +00:00
|
|
|
|
2010-04-09 20:43:58 +00:00
|
|
|
# props
|
|
|
|
lines[:] = []
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2010-04-10 18:35:50 +00: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 09:27:25 +00:00
|
|
|
|
2010-04-10 18:35:50 +00:00
|
|
|
if _BPY_STRUCT_FAKE:
|
|
|
|
for key, descr in descr_items:
|
|
|
|
if type(descr) == GetSetDescriptorType:
|
2010-09-03 09:21:40 +00:00
|
|
|
lines.append(" * :class:`%s.%s`\n" % (_BPY_STRUCT_FAKE, key))
|
2010-04-10 18:35:50 +00:00
|
|
|
|
2010-04-09 20:43:58 +00:00
|
|
|
for base in bases:
|
|
|
|
for prop in base.properties:
|
2010-09-03 09:21:40 +00:00
|
|
|
lines.append(" * :class:`%s.%s`\n" % (base.identifier, prop.identifier))
|
2010-04-09 20:43:58 +00:00
|
|
|
|
|
|
|
for identifier, py_prop in base.get_py_properties():
|
2010-09-03 09:21:40 +00:00
|
|
|
lines.append(" * :class:`%s.%s`\n" % (base.identifier, identifier))
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2010-04-10 18:35:50 +00:00
|
|
|
for identifier, py_prop in base.get_py_properties():
|
2010-09-03 09:21:40 +00:00
|
|
|
lines.append(" * :class:`%s.%s`\n" % (base.identifier, identifier))
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2010-04-09 20:43:58 +00:00
|
|
|
if lines:
|
|
|
|
fw(".. rubric:: Inherited Properties\n\n")
|
2010-09-03 09:21:40 +00:00
|
|
|
|
|
|
|
fw(".. hlist::\n")
|
2010-09-03 14:53:54 +00:00
|
|
|
fw(" :columns: 2\n\n")
|
2010-09-03 09:21:40 +00:00
|
|
|
|
2010-04-09 20:43:58 +00:00
|
|
|
for line in lines:
|
|
|
|
fw(line)
|
|
|
|
fw("\n")
|
|
|
|
|
|
|
|
# funcs
|
|
|
|
lines[:] = []
|
2010-04-10 18:35:50 +00:00
|
|
|
|
|
|
|
if _BPY_STRUCT_FAKE:
|
|
|
|
for key, descr in descr_items:
|
|
|
|
if type(descr) == MethodDescriptorType:
|
2010-09-03 09:21:40 +00:00
|
|
|
lines.append(" * :class:`%s.%s`\n" % (_BPY_STRUCT_FAKE, key))
|
2010-04-10 18:35:50 +00:00
|
|
|
|
2010-04-09 20:43:58 +00:00
|
|
|
for base in bases:
|
|
|
|
for func in base.functions:
|
2010-09-03 09:21:40 +00:00
|
|
|
lines.append(" * :class:`%s.%s`\n" % (base.identifier, func.identifier))
|
2010-04-09 20:43:58 +00:00
|
|
|
for identifier, py_func in base.get_py_functions():
|
2010-09-03 09:21:40 +00:00
|
|
|
lines.append(" * :class:`%s.%s`\n" % (base.identifier, identifier))
|
2010-04-09 20:43:58 +00:00
|
|
|
|
|
|
|
if lines:
|
|
|
|
fw(".. rubric:: Inherited Functions\n\n")
|
2010-09-03 09:21:40 +00:00
|
|
|
|
|
|
|
fw(".. hlist::\n")
|
2010-09-03 14:53:54 +00:00
|
|
|
fw(" :columns: 2\n\n")
|
2010-09-03 09:21:40 +00:00
|
|
|
|
2010-04-09 20:43:58 +00:00
|
|
|
for line in lines:
|
|
|
|
fw(line)
|
|
|
|
fw("\n")
|
|
|
|
|
2011-02-04 09:27:25 +00:00
|
|
|
lines[:] = []
|
2010-04-09 20:43:58 +00:00
|
|
|
|
2009-12-25 15:50:53 +00:00
|
|
|
if struct.references:
|
|
|
|
# use this otherwise it gets in the index for a normal heading.
|
|
|
|
fw(".. rubric:: References\n\n")
|
|
|
|
|
2010-09-03 09:21:40 +00:00
|
|
|
fw(".. hlist::\n")
|
2010-09-03 14:53:54 +00:00
|
|
|
fw(" :columns: 2\n\n")
|
2010-09-03 09:21:40 +00:00
|
|
|
|
2009-12-25 15:50:53 +00: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 09:21:40 +00:00
|
|
|
fw(" * :class:`%s`\n" % ref)
|
2009-12-25 15:50:53 +00:00
|
|
|
fw("\n")
|
|
|
|
|
2011-02-18 08:47:37 +00:00
|
|
|
# docs last?, disable for now
|
|
|
|
# write_example_ref("", fw, "bpy.types.%s" % struct.identifier)
|
2011-02-22 05:23:20 +00:00
|
|
|
file.close()
|
2011-02-18 08:47:37 +00:00
|
|
|
|
2011-02-16 05:18:10 +00: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 09:27:25 +00:00
|
|
|
|
2011-03-22 04:28:51 +00: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 05:18:10 +00:00
|
|
|
file = open(filepath, "w")
|
|
|
|
fw = file.write
|
2010-04-10 18:35:50 +00:00
|
|
|
|
2011-03-22 04:28:51 +00:00
|
|
|
write_title(fw, class_name, "=")
|
|
|
|
|
2011-02-16 05:18:10 +00:00
|
|
|
fw(".. module:: bpy.types\n")
|
|
|
|
fw("\n")
|
2010-04-10 18:35:50 +00:00
|
|
|
|
2011-03-22 04:28:51 +00: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 18:35:50 +00:00
|
|
|
|
2011-03-22 04:28:51 +00:00
|
|
|
fw(".. class:: %s\n\n" % class_name)
|
|
|
|
fw(" %s\n\n" % descr_str)
|
2011-02-16 05:18:10 +00:00
|
|
|
fw(" .. note::\n\n")
|
2011-03-22 04:28:51 +00: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 18:35:50 +00:00
|
|
|
|
2011-03-22 04:28:51 +00:00
|
|
|
descr_items = [(key, descr) for key, descr in sorted(class_value.__dict__.items()) if not key.startswith("__")]
|
2010-04-10 18:35:50 +00:00
|
|
|
|
2011-02-16 05:18:10 +00:00
|
|
|
for key, descr in descr_items:
|
|
|
|
if type(descr) == MethodDescriptorType: # GetSetDescriptorType, GetSetDescriptorType's are not documented yet
|
2011-03-22 04:28:51 +00:00
|
|
|
py_descr2sphinx(" ", fw, descr, "bpy.types", class_name, key)
|
2010-04-10 18:35:50 +00:00
|
|
|
|
2011-02-16 05:18:10 +00:00
|
|
|
for key, descr in descr_items:
|
|
|
|
if type(descr) == GetSetDescriptorType:
|
2011-03-22 04:28:51 +00:00
|
|
|
py_descr2sphinx(" ", fw, descr, "bpy.types", class_name, key)
|
2011-02-22 05:23:20 +00:00
|
|
|
file.close()
|
2010-04-10 18:35:50 +00:00
|
|
|
|
2011-03-22 04:28:51 +00: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 13:47:56 +00:00
|
|
|
# operators
|
2009-12-25 15:50:53 +00:00
|
|
|
def write_ops():
|
2011-05-05 14:45:24 +00:00
|
|
|
API_BASEURL = "http://svn.blender.org/svnroot/bf-blender/trunk/blender/release/scripts"
|
|
|
|
API_BASEURL_ADDON = "http://svn.blender.org/svnroot/bf-extensions/trunk/py/scripts"
|
|
|
|
API_BASEURL_ADDON_CONTRIB = "http://svn.blender.org/svnroot/bf-extensions/contrib/py/scripts"
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2011-02-22 05:23:20 +00:00
|
|
|
op_modules = {}
|
|
|
|
for op in ops.values():
|
|
|
|
op_modules.setdefault(op.module_name, []).append(op)
|
|
|
|
del op
|
2011-02-25 16:19:50 +00:00
|
|
|
|
2011-02-22 05:23:20 +00: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 04:28:51 +00:00
|
|
|
|
|
|
|
write_title(fw, title, "=")
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2011-02-22 05:23:20 +00:00
|
|
|
fw(".. module:: bpy.ops.%s\n\n" % op_module_name)
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2011-02-22 05:23:20 +00:00
|
|
|
ops_mod.sort(key=lambda op: op.func_name)
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2011-02-22 05:23:20 +00: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 18:35:50 +00:00
|
|
|
|
2011-02-22 05:23:20 +00: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-11 22:41:13 +00:00
|
|
|
|
2011-02-22 05:23:20 +00:00
|
|
|
fw(" %s\n\n" % operator_description)
|
|
|
|
for prop in op.args:
|
|
|
|
write_param(" ", fw, prop)
|
|
|
|
if op.args:
|
|
|
|
fw("\n")
|
2010-06-11 22:41:13 +00:00
|
|
|
|
2011-02-22 05:23:20 +00:00
|
|
|
location = op.get_location()
|
|
|
|
if location != (None, None):
|
2011-05-05 14:45:24 +00:00
|
|
|
if location[0].startswith("addons_contrib" + os.sep):
|
|
|
|
url_base = API_BASEURL_ADDON_CONTRIB
|
|
|
|
elif location[0].startswith("addons" + os.sep):
|
|
|
|
url_base = API_BASEURL_ADDON
|
|
|
|
else:
|
|
|
|
url_base = API_BASEURL
|
|
|
|
|
|
|
|
fw(" :file: `%s <%s/%s>`_:%d\n\n" % (location[0], url_base, location[0], location[1]))
|
2009-12-26 16:47:25 +00:00
|
|
|
|
2011-02-22 05:23:20 +00:00
|
|
|
file.close()
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2011-02-16 05:18:10 +00: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
|
|
|
|
|
|
|
|
version_string_fp = "_".join(str(v) for v in bpy.app.version)
|
|
|
|
|
2011-04-12 16:56:15 +00:00
|
|
|
if bpy.app.version_cycle == "release":
|
|
|
|
version_string_pdf = "%s%s_release" % ("_".join(str(v) for v in bpy.app.version[:2]), bpy.app.version_char)
|
|
|
|
else:
|
|
|
|
version_string_pdf = version_string_fp
|
|
|
|
|
2011-02-16 05:18:10 +00:00
|
|
|
fw("project = 'Blender'\n")
|
|
|
|
# fw("master_doc = 'index'\n")
|
|
|
|
fw("copyright = u'Blender Foundation'\n")
|
2011-04-12 12:09:38 +00:00
|
|
|
fw("version = '%s - API'\n" % version_string)
|
|
|
|
fw("release = '%s - API'\n" % version_string)
|
2011-02-16 05:18:10 +00:00
|
|
|
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")
|
2011-04-13 14:43:11 +00:00
|
|
|
fw("Welcome, this document is an API reference for Blender %s. built %s.\n" % (version_string, bpy.app.build_date))
|
2011-02-16 05:18:10 +00:00
|
|
|
fw("\n")
|
2011-04-12 16:56:15 +00:00
|
|
|
fw("`A PDF version of this document is also available <blender_python_reference_%s.pdf>`_\n" % version_string_pdf)
|
2011-04-13 14:43:11 +00:00
|
|
|
|
|
|
|
fw("\n")
|
|
|
|
|
2011-08-25 04:25:33 +00:00
|
|
|
if not EXCLUDE_INFO_DOCS:
|
|
|
|
fw("============================\n")
|
|
|
|
fw("Blender/Python Documentation\n")
|
|
|
|
fw("============================\n")
|
|
|
|
fw("\n")
|
|
|
|
fw("\n")
|
|
|
|
fw(".. toctree::\n")
|
|
|
|
fw(" :maxdepth: 1\n\n")
|
|
|
|
for info, info_desc in INFO_DOCS:
|
|
|
|
fw(" %s <%s>\n\n" % (info_desc, info))
|
|
|
|
fw("\n")
|
2011-02-16 05:18:10 +00:00
|
|
|
|
|
|
|
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")
|
2011-07-01 11:16:42 +00:00
|
|
|
if "bgl" not in EXCLUDE_MODULES:
|
|
|
|
fw(" bgl.rst\n\n")
|
2011-02-16 05:18:10 +00:00
|
|
|
if "blf" not in EXCLUDE_MODULES:
|
|
|
|
fw(" blf.rst\n\n")
|
|
|
|
if "aud" not in EXCLUDE_MODULES:
|
|
|
|
fw(" aud.rst\n\n")
|
2011-05-28 07:47:58 +00:00
|
|
|
if "bpy_extras" not in EXCLUDE_MODULES:
|
|
|
|
fw(" bpy_extras.rst\n\n")
|
2011-02-16 05:18:10 +00:00
|
|
|
|
|
|
|
# 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")
|
2011-07-07 19:23:51 +00:00
|
|
|
fw(" bge.texture.rst\n\n")
|
2011-02-16 05:18:10 +00:00
|
|
|
fw(" bge.events.rst\n\n")
|
2011-07-08 02:59:25 +00:00
|
|
|
fw(" bge.constraints.rst\n\n")
|
2011-02-16 05:18:10 +00:00
|
|
|
|
2011-04-07 07:53:28 +00:00
|
|
|
# rna generated change log
|
|
|
|
fw("========\n")
|
|
|
|
fw("API Info\n")
|
|
|
|
fw("========\n")
|
|
|
|
fw("\n")
|
|
|
|
fw(".. toctree::\n")
|
|
|
|
fw(" :maxdepth: 1\n\n")
|
|
|
|
fw(" change_log.rst\n\n")
|
|
|
|
|
2011-04-13 14:43:11 +00:00
|
|
|
fw("\n")
|
|
|
|
fw("\n")
|
|
|
|
fw(".. note:: The Blender Python API has areas which are still in development.\n")
|
|
|
|
fw(" \n")
|
|
|
|
fw(" The following areas are subject to change.\n")
|
|
|
|
fw(" * operator behavior, names and arguments\n")
|
|
|
|
fw(" * mesh creation and editing functions\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(" * render engine integration\n")
|
|
|
|
fw(" * modules: bgl, mathutils & game engine.\n")
|
|
|
|
fw("\n")
|
|
|
|
|
2011-02-16 05:18:10 +00:00
|
|
|
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 08:47:37 +00:00
|
|
|
write_example_ref("", fw, "bpy.ops")
|
2011-02-16 05:18:10 +00: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
|
2011-05-28 07:47:58 +00:00
|
|
|
pymodule2sphinx(BASEPATH, "bpy.utils", module, "Utilities")
|
2011-02-16 05:18:10 +00:00
|
|
|
|
|
|
|
if "bpy.path" not in EXCLUDE_MODULES:
|
|
|
|
from bpy import path as module
|
2011-05-28 07:47:58 +00:00
|
|
|
pymodule2sphinx(BASEPATH, "bpy.path", module, "Path Utilities")
|
|
|
|
|
|
|
|
if "bpy_extras" not in EXCLUDE_MODULES:
|
|
|
|
import bpy_extras as module
|
|
|
|
pymodule2sphinx(BASEPATH, "bpy_extras", module, "Extra Utilities")
|
2011-02-16 05:18:10 +00:00
|
|
|
|
|
|
|
# C modules
|
|
|
|
if "bpy.app" not in EXCLUDE_MODULES:
|
|
|
|
from bpy import app as module
|
2011-05-28 07:47:58 +00:00
|
|
|
pymodule2sphinx(BASEPATH, "bpy.app", module, "Application Data")
|
2011-02-16 05:18:10 +00:00
|
|
|
|
|
|
|
if "bpy.props" not in EXCLUDE_MODULES:
|
|
|
|
from bpy import props as module
|
2011-05-28 07:47:58 +00:00
|
|
|
pymodule2sphinx(BASEPATH, "bpy.props", module, "Property Definitions")
|
2011-02-16 05:18:10 +00:00
|
|
|
|
|
|
|
if "mathutils" not in EXCLUDE_MODULES:
|
|
|
|
import mathutils as module
|
2011-05-28 07:47:58 +00:00
|
|
|
pymodule2sphinx(BASEPATH, "mathutils", module, "Math Types & Utilities")
|
2011-02-16 05:18:10 +00:00
|
|
|
|
|
|
|
if "mathutils.geometry" not in EXCLUDE_MODULES:
|
|
|
|
import mathutils.geometry as module
|
2011-05-28 07:47:58 +00:00
|
|
|
pymodule2sphinx(BASEPATH, "mathutils.geometry", module, "Geometry Utilities")
|
2011-02-16 05:18:10 +00:00
|
|
|
|
2011-07-01 11:16:42 +00:00
|
|
|
if "blf" not in EXCLUDE_MODULES:
|
2011-02-16 05:18:10 +00:00
|
|
|
import blf as module
|
2011-05-28 07:47:58 +00:00
|
|
|
pymodule2sphinx(BASEPATH, "blf", module, "Font Drawing")
|
2011-02-16 05:18:10 +00:00
|
|
|
|
2011-07-01 11:16:42 +00:00
|
|
|
if "bgl" not in EXCLUDE_MODULES:
|
|
|
|
#import bgl as module
|
|
|
|
#pymodule2sphinx(BASEPATH, "bgl", module, "Blender OpenGl wrapper")
|
|
|
|
#del module
|
|
|
|
import shutil
|
|
|
|
shutil.copy2(os.path.join(BASEPATH, "..", "rst", "bgl.rst"), BASEPATH)
|
2011-02-16 05:18:10 +00:00
|
|
|
|
|
|
|
if "aud" not in EXCLUDE_MODULES:
|
|
|
|
import aud as module
|
2011-05-28 07:47:58 +00:00
|
|
|
pymodule2sphinx(BASEPATH, "aud", module, "Audio System")
|
2011-02-16 05:18:10 +00:00
|
|
|
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)
|
2011-07-07 19:23:51 +00:00
|
|
|
shutil.copy2(os.path.join(BASEPATH, "..", "rst", "bge.texture.rst"), BASEPATH)
|
2011-02-16 05:18:10 +00:00
|
|
|
shutil.copy2(os.path.join(BASEPATH, "..", "rst", "bge.events.rst"), BASEPATH)
|
2011-07-08 02:59:25 +00:00
|
|
|
shutil.copy2(os.path.join(BASEPATH, "..", "rst", "bge.constraints.rst"), BASEPATH)
|
2011-02-16 05:18:10 +00:00
|
|
|
|
2011-04-07 07:53:28 +00:00
|
|
|
shutil.copy2(os.path.join(BASEPATH, "..", "rst", "change_log.rst"), BASEPATH)
|
|
|
|
|
2011-08-25 04:25:33 +00:00
|
|
|
if not EXCLUDE_INFO_DOCS:
|
|
|
|
for info, info_desc in INFO_DOCS:
|
|
|
|
shutil.copy2(os.path.join(BASEPATH, "..", "rst", info), BASEPATH)
|
|
|
|
|
2011-02-16 05:18:10 +00:00
|
|
|
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 04:28:51 +00:00
|
|
|
|
|
|
|
write_title(fw, title, "=")
|
|
|
|
|
2011-02-16 05:18:10 +00:00
|
|
|
fw(".. module:: bpy.types\n\n")
|
|
|
|
file.close()
|
|
|
|
|
|
|
|
# bpy.types and bpy.ops
|
|
|
|
pyrna2sphinx(BASEPATH)
|
2009-12-25 15:50:53 +00:00
|
|
|
|
|
|
|
file.close()
|
|
|
|
|
2011-02-04 09:27:25 +00:00
|
|
|
|
2010-07-19 13:36:10 +00:00
|
|
|
def main():
|
2011-06-27 04:50:08 +00:00
|
|
|
import shutil
|
|
|
|
|
|
|
|
script_dir = os.path.dirname(__file__)
|
|
|
|
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")
|
|
|
|
# only for partial updates
|
|
|
|
path_in_tmp = path_in + "-tmp"
|
|
|
|
|
|
|
|
if not os.path.exists(path_in):
|
|
|
|
os.mkdir(path_in)
|
|
|
|
|
|
|
|
for f in os.listdir(path_examples):
|
|
|
|
if f.endswith(".py"):
|
|
|
|
EXAMPLE_SET.add(os.path.splitext(f)[0])
|
|
|
|
|
|
|
|
# only for full updates
|
|
|
|
if _BPY_FULL_REBUILD:
|
|
|
|
shutil.rmtree(path_in, True)
|
|
|
|
shutil.rmtree(path_out, True)
|
2009-12-25 15:50:53 +00:00
|
|
|
else:
|
2011-06-27 04:50:08 +00:00
|
|
|
# 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))
|
|
|
|
|
|
|
|
# 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("\tdeprecated: %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
|
|
|
|
|
|
|
|
if do_copy:
|
|
|
|
print("\tupdating: %s" % f)
|
|
|
|
shutil.copy(f_from, f_to)
|
|
|
|
'''else:
|
|
|
|
print("\tkeeping: %s" % f) # eh, not that useful'''
|
|
|
|
|
|
|
|
EXAMPLE_SET_UNUSED = EXAMPLE_SET - EXAMPLE_SET_USED
|
|
|
|
if EXAMPLE_SET_UNUSED:
|
|
|
|
print("\nUnused 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 15:50:53 +00:00
|
|
|
|
|
|
|
import sys
|
|
|
|
sys.exit()
|
2010-07-19 13:36:10 +00:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|