Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2012-11-27 10:56:51 +0400
committerCampbell Barton <ideasman42@gmail.com>2012-11-27 10:56:51 +0400
commit9775f1d74301615d7898e70b0e85608d0895b523 (patch)
treecb9c8bb9e623582e4104fc70784f432305eb2275 /doc
parent90666d34369e914e09030e85d497271cf77454db (diff)
generate api reference for 'bmesh.ops', restructured text is extracted from bmesh_opdefines.c.
see: http://www.blender.org/documentation/blender_python_api_2_64_9/bmesh.ops.html
Diffstat (limited to 'doc')
-rw-r--r--doc/python_api/rst_from_bmesh_opdefines.py370
-rw-r--r--doc/python_api/sphinx_doc_gen.py18
2 files changed, 385 insertions, 3 deletions
diff --git a/doc/python_api/rst_from_bmesh_opdefines.py b/doc/python_api/rst_from_bmesh_opdefines.py
new file mode 100644
index 00000000000..5803315ff86
--- /dev/null
+++ b/doc/python_api/rst_from_bmesh_opdefines.py
@@ -0,0 +1,370 @@
+# ##### 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,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+# This is a quite stupid script which extracts bmesh api docs from
+# 'bmesh_opdefines.c' in order to avoid having to add a lot of introspection
+# data access into the api.
+#
+# The script is stupid becase it makes assumptions about formatting...
+# that each arg has its own line, that comments above or directly after will be __doc__ etc...
+#
+# We may want to replace this script with something else one day but for now its good enough.
+# if it needs large updates it may be better to rewrite using a real parser or
+# add introspection into bmesh.ops.
+# - campbell
+
+import os
+
+CURRENT_DIR = os.path.abspath(os.path.dirname(__file__))
+SOURCE_DIR = os.path.normpath(os.path.abspath(os.path.normpath(os.path.join(CURRENT_DIR, "..", ".."))))
+FILE_OP_DEFINES_C = os.path.join(SOURCE_DIR, "source", "blender", "bmesh", "intern", "bmesh_opdefines.c")
+OUT_RST = os.path.join(CURRENT_DIR, "rst", "bmesh.ops.rst")
+
+HEADER = r"""
+BMesh Operators
+===============
+
+.. module:: bmesh.ops
+
+This module gives access to low level bmesh operations.
+
+Most operators take input and return output, they can be chained together
+to perform useful operations.
+
+.. note::
+
+ This API us new in 2.65 and not yet well tested.
+
+
+"""
+
+
+def main():
+ fsrc = open(FILE_OP_DEFINES_C, 'r', encoding="utf-8")
+
+ blocks = []
+
+ is_block = False
+ is_comment = False # /* global comments only */
+
+ comment_ctx = None
+ block_ctx = None
+
+ for l in fsrc:
+ l = l[:-1]
+ # weak but ok
+ if ("BMOpDefine" in l and l.split()[1] == "BMOpDefine") and not "bmo_opdefines[]" in l:
+ is_block = True
+ block_ctx = []
+ blocks.append((comment_ctx, block_ctx))
+ elif l.strip().startswith("/*"):
+ is_comment = True
+ comment_ctx = []
+
+ if is_block:
+ if l.strip().startswith("//"):
+ pass
+ else:
+ # remove c++ comment if we have one
+ cpp_comment = l.find("//")
+ if cpp_comment != -1:
+ l = l[:cpp_comment]
+
+ block_ctx.append(l)
+
+ if l.strip() == "};":
+ is_block = False
+ comment_ctx = None
+
+ if is_comment:
+ c_comment_start = l.find("/*")
+ if c_comment_start != -1:
+ l = l[c_comment_start + 2:]
+
+ c_comment_end = l.find("*/")
+ if c_comment_end != -1:
+ l = l[:c_comment_end]
+
+ is_comment = False
+ comment_ctx.append(l)
+
+ fsrc.close()
+ del fsrc
+
+
+ # namespace hack
+ vars = (
+ "BMO_OP_SLOT_ELEMENT_BUF",
+ "BMO_OP_SLOT_BOOL",
+ "BMO_OP_SLOT_FLT",
+ "BMO_OP_SLOT_INT",
+ "BMO_OP_SLOT_MAT",
+ "BMO_OP_SLOT_VEC",
+ "BMO_OP_SLOT_PTR",
+ "BMO_OP_SLOT_MAPPING",
+
+ "BMO_OP_SLOT_SUBTYPE_MAP_ELEM",
+ "BMO_OP_SLOT_SUBTYPE_MAP_BOOL",
+ "BMO_OP_SLOT_SUBTYPE_MAP_INT",
+ "BMO_OP_SLOT_SUBTYPE_MAP_FLOAT",
+ "BMO_OP_SLOT_SUBTYPE_MAP_EMPTY",
+ "BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL",
+
+ "BMO_OP_SLOT_SUBTYPE_PTR_SCENE",
+ "BMO_OP_SLOT_SUBTYPE_PTR_OBJECT",
+ "BMO_OP_SLOT_SUBTYPE_PTR_MESH",
+ "BMO_OP_SLOT_SUBTYPE_PTR_BMESH",
+
+ "BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE",
+
+ "BM_VERT",
+ "BM_EDGE",
+ "BM_FACE",
+
+ "BMO_OP_FLAG_UNTAN_MULTIRES",
+ )
+ vars_dict = {}
+ for i, v in enumerate(vars):
+ vars_dict[v] = (1 << i)
+ globals().update(vars_dict)
+ # reverse lookup
+ vars_dict_reverse = {v: k for k, v in vars_dict.items()}
+ # end namespace hack
+
+ blocks_py = []
+ for comment, b in blocks:
+ # magic, translate into python
+ b[0] = b[0].replace("static BMOpDefine ", "")
+
+ for i, l in enumerate(b):
+ l = l.strip()
+ l = l.replace("{", "(")
+ l = l.replace("}", ")")
+
+ if l.startswith("/*"):
+ l = l.replace("/*", "'''own <")
+ else:
+ l = l.replace("/*", "'''inline <")
+ l = l.replace("*/", ">''',")
+
+ # exec func. eg: bmo_rotate_edges_exec,
+ if l.startswith("bmo_") and l.endswith("_exec,"):
+ l = "None,"
+ b[i] = l
+
+ #for l in b:
+ # print(l)
+
+ text = "\n".join(b)
+ global_namespace = {
+ "__file__": "generated",
+ "__name__": "__main__",
+ }
+
+ global_namespace.update(vars_dict)
+
+ text_a, text_b = text.split("=", 1)
+ text = "result = " + text_b
+ exec(compile(text, "generated", 'exec'), global_namespace)
+ # print(global_namespace["result"])
+ blocks_py.append((comment, global_namespace["result"]))
+
+
+ # ---------------------
+ # Now convert into rst.
+ fout = open(OUT_RST, 'w', encoding="utf-8")
+ fw = fout.write
+ fw(HEADER)
+ for comment, b in blocks_py:
+ args_in = None
+ args_out = None
+ for member in b[1:]:
+ if type(member) == tuple:
+ if args_in is None:
+ args_in = member
+ elif args_out is None:
+ args_out = member
+ break
+
+ args_in_index = []
+ args_out_index = []
+
+ if args_in is not None:
+ args_in_index[:] = [i for (i, a) in enumerate(args_in) if type(a) == tuple]
+ if args_out is not None:
+ args_out_index[:] = [i for (i, a) in enumerate(args_out) if type(a) == tuple]
+
+ fw(".. function:: %s(%s)\n\n" % (b[0], ", ".join([args_in[i][0] for i in args_in_index])))
+
+ # -- wash the comment
+ comment_washed = []
+ for i, l in enumerate(comment):
+ assert((l.strip() == "") or
+ (l in {"/*", " *"}) or
+ (l.startswith(("/* ", " * "))))
+
+ l = l[3:]
+ if i == 0 and not l.strip():
+ continue
+ if l.strip():
+ l = " " + l
+ comment_washed.append(l)
+
+ fw("\n".join(comment_washed))
+ fw("\n")
+ # -- done
+
+
+ # get the args
+ def get_args_wash(args, args_index):
+ args_wash = []
+ for i in args_index:
+ arg = args[i]
+ if len(arg) == 3:
+ name, tp, tp_sub = arg
+ elif len(arg) == 2:
+ name, tp = arg
+ tp_sub = None
+ else:
+ print(arg)
+ assert(0)
+
+ tp_str = ""
+
+ comment_prev = ""
+ comment_next = ""
+ if i != 0:
+ comment_prev = args[i + 1]
+ if type(comment_prev) == str and comment_prev.startswith("our <"):
+ comment_prev = comment_next[5:-1] # strip inline <...>
+ else:
+ comment_prev = ""
+
+ if i + 1 < len(args):
+ comment_next = args[i + 1]
+ if type(comment_next) == str and comment_next.startswith("inline <"):
+ comment_next = comment_next[8:-1] # strip inline <...>
+ else:
+ comment_next = ""
+
+ comment = ""
+ if comment_prev:
+ comment += comment_prev.strip()
+ if comment_next:
+ comment += ("\n" if comment_prev else "") + comment_next.strip()
+
+ if tp == BMO_OP_SLOT_FLT:
+ tp_str = "float"
+ elif tp == BMO_OP_SLOT_INT:
+ tp_str = "int"
+ elif tp == BMO_OP_SLOT_BOOL:
+ tp_str = "bool"
+ elif tp == BMO_OP_SLOT_MAT:
+ tp_str = "matrix"
+ elif tp == BMO_OP_SLOT_VEC:
+ tp_str = "matrix"
+ elif tp == BMO_OP_SLOT_PTR:
+ tp_str = "dict"
+ assert(tp_sub is not None)
+ if tp_sub == BMO_OP_SLOT_SUBTYPE_PTR_BMESH:
+ tp_str = "BMesh"
+ elif tp_sub == BMO_OP_SLOT_SUBTYPE_PTR_SCENE:
+ tp_str = "Scene"
+ elif tp_sub == BMO_OP_SLOT_SUBTYPE_PTR_OBJECT:
+ tp_str = "Object"
+ elif tp_sub == BMO_OP_SLOT_SUBTYPE_PTR_MESH:
+ tp_str = "Mesh"
+ else:
+ print("Cant find", vars_dict_reverse[tp_sub])
+ assert(0)
+
+ elif tp == BMO_OP_SLOT_ELEMENT_BUF:
+ assert(tp_sub is not None)
+
+ ls = []
+ if tp_sub & BM_VERT: ls.append("vert")
+ if tp_sub & BM_EDGE: ls.append("edge")
+ if tp_sub & BM_FACE: ls.append("face")
+ assert(ls) # must be at least one
+
+ if tp_sub & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE:
+ tp_str = "/".join(ls)
+ else:
+ tp_str = ("list of (%s)" % ", ".join(ls))
+
+ del ls
+ elif tp == BMO_OP_SLOT_MAPPING:
+ if tp_sub & BMO_OP_SLOT_SUBTYPE_MAP_EMPTY:
+ tp_str = "set of vert/edge/face type"
+ else:
+ tp_str = "dict mapping vert/edge/face types to "
+ if tp_sub == BMO_OP_SLOT_SUBTYPE_MAP_BOOL:
+ tp_str += "bool"
+ elif tp_sub == BMO_OP_SLOT_SUBTYPE_MAP_INT:
+ tp_str += "int"
+ elif tp_sub == BMO_OP_SLOT_SUBTYPE_MAP_FLOAT:
+ tp_str += "float"
+ elif tp_sub == BMO_OP_SLOT_SUBTYPE_MAP_ELEM:
+ tp_str += "vert/edge/face elements"
+ elif tp_sub == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL:
+ tp_str += "unknown internal data, not compatible with python"
+ else:
+ print("Cant find", vars_dict_reverse[tp_sub])
+ assert(0)
+ else:
+ print("Cant find", vars_dict_reverse[tp])
+ assert(0)
+
+ args_wash.append((name, tp_str, comment))
+ return args_wash
+ # end get_args_wash
+
+
+ args_in_wash = get_args_wash(args_in, args_in_index)
+ args_out_wash = get_args_wash(args_out, args_out_index)
+
+ for (name, tp, comment) in args_in_wash:
+ if comment == "":
+ comment = "Undocumented."
+
+ fw(" :arg %s: %s\n" % (name, comment))
+ fw(" :type %s: %s\n" % (name, tp))
+
+ if args_out_wash:
+ fw(" :return:\n\n")
+
+ for (name, tp, comment) in args_out_wash:
+ assert(name.endswith(".out"))
+ name = name[:-4]
+ fw(" - ``%s``: %s\n\n" % (name, comment))
+ fw(" **type** %s\n" % tp)
+
+ fw("\n")
+ fw(" :rtype: dict with string keys\n")
+
+ fw("\n\n")
+
+ fout.close()
+ del fout
+ print(OUT_RST)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py
index 410612fabd5..1814261fc71 100644
--- a/doc/python_api/sphinx_doc_gen.py
+++ b/doc/python_api/sphinx_doc_gen.py
@@ -35,7 +35,7 @@ API dump in RST files
./blender.bin --background --python doc/python_api/sphinx_doc_gen.py -- --output ../python_api
For quick builds:
- ./blender.bin --background --python doc/python_api/sphinx_doc_gen.py -- --partial
+ ./blender.bin --background --python doc/python_api/sphinx_doc_gen.py -- --partial bmesh.*
Sphinx: HTML generation
@@ -245,6 +245,7 @@ else:
"bgl",
"blf",
"bmesh",
+ "bmesh.ops",
"bmesh.types",
"bmesh.utils",
"bpy.app",
@@ -297,7 +298,7 @@ try:
__import__("aud")
except ImportError:
BPY_LOGGER.debug("Warning: Built without 'aud' module, docs incomplete...")
- EXCLUDE_MODULES = EXCLUDE_MODULES + ("aud", )
+ EXCLUDE_MODULES = list(EXCLUDE_MODULES) + ["aud"]
# examples
EXAMPLES_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, "examples"))
@@ -1472,6 +1473,11 @@ def write_sphinx_conf_py(basepath):
file.close()
+def execfile(filepath):
+ global_namespace = {"__file__": filepath, "__name__": "__main__"}
+ exec(compile(open(filepath).read(), filepath, 'exec'), global_namespace)
+
+
def write_rst_contents(basepath):
'''
Write the rst file of the main page, needed for sphinx (index.html)
@@ -1533,13 +1539,17 @@ def write_rst_contents(basepath):
# misc
"bgl", "blf", "gpu", "aud", "bpy_extras",
# bmesh
- "bmesh", "bmesh.types", "bmesh.utils",
+ "bmesh", "bmesh.types", "bmesh.utils", "bmesh.ops",
)
for mod in standalone_modules:
if mod not in EXCLUDE_MODULES:
fw(" %s\n\n" % mod)
+ # special case, this 'bmesh.ops.rst' is extracted from C source
+ if "bmesh.ops" not in EXCLUDE_MODULES:
+ execfile(os.path.join(SCRIPT_DIR, "rst_from_bmesh_opdefines.py"))
+
# game engine
if "bge" not in EXCLUDE_MODULES:
fw(title_string("Game Engine Modules", "=", double=True))
@@ -1701,6 +1711,8 @@ def copy_handwritten_rsts(basepath):
"bgl", # "Blender OpenGl wrapper"
"gpu", # "GPU Shader Module"
+ "bmesh.ops", # generated by rst_from_bmesh_opdefines.py
+
# includes...
"include__bmesh",
]