diff options
author | Campbell Barton <campbell@blender.org> | 2022-05-18 09:59:16 +0300 |
---|---|---|
committer | Campbell Barton <campbell@blender.org> | 2022-05-18 10:06:03 +0300 |
commit | c8edc458d13c0483907d0fe6f44f6e2887263b57 (patch) | |
tree | dfa5cc3575a312c44e10d3c5d406318628967a6a | |
parent | 88fbe94d70dc850b6534a5351dd4da4d844e2120 (diff) |
PyDoc: support building full API docs on macOS & WIN32
Accessing context members depended on `ctypes` to access symbols
which were hidden for macOS & WIN32.
Add an API call that doesn't require the symbols to be exported.
This allows most symbols to be hidden on Linux, see D14971.
-rw-r--r-- | doc/python_api/sphinx_doc_gen.py | 33 | ||||
-rw-r--r-- | source/blender/python/intern/bpy.c | 65 |
2 files changed, 72 insertions, 26 deletions
diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index eba12b75b63..1c52bb3e57d 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -1200,34 +1200,18 @@ def pycontext2sphinx(basepath): del write_contex_cls # end - # 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", - "clip_context_dir", - "sequencer_context_dir", - "file_context_dir", - ) + # Internal API call only intended to be used to extract context members. + from _bpy import context_members + context_member_map = context_members() + del context_members # Track unique for `context_strings` to validate `context_type_map`. unique_context_strings = set() - blend_cdll = ctypes.CDLL("") - for ctx_str in context_strings: + for ctx_str, ctx_members in sorted(context_member_map.items()): 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(encoding="ascii") + for member in ctx_members: unique_all_len = len(unique) unique.add(member) member_visited = unique_all_len == len(unique) @@ -2167,10 +2151,7 @@ def rna2sphinx(basepath): # context if "bpy.context" not in EXCLUDE_MODULES: - # one of a kind, context doc (uses ctypes to extract info!) - # doesn't work on mac and windows - if PLATFORM not in {"darwin", "windows"}: - pycontext2sphinx(basepath) + pycontext2sphinx(basepath) # internal modules write_rst_bpy(basepath) # bpy, disabled by default diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c index 748a501ef76..9d8602d51bd 100644 --- a/source/blender/python/intern/bpy.c +++ b/source/blender/python/intern/bpy.c @@ -400,6 +400,62 @@ static PyObject *bpy_unescape_identifier(PyObject *UNUSED(self), PyObject *value return value_unescape; } +/** + * \note only exposed for generating documentation, see: `doc/python_api/sphinx_doc_gen.py`. + */ +PyDoc_STRVAR( + bpy_context_members_doc, + ".. function:: context_members()\n" + "\n" + " :return: A dict where the key is the context and the value is a tuple of it's members.\n" + " :rtype: dict\n"); +static PyObject *bpy_context_members(PyObject *UNUSED(self)) +{ + extern const char *buttons_context_dir[]; + extern const char *clip_context_dir[]; + extern const char *file_context_dir[]; + extern const char *image_context_dir[]; + extern const char *node_context_dir[]; + extern const char *screen_context_dir[]; + extern const char *sequencer_context_dir[]; + extern const char *text_context_dir[]; + extern const char *view3d_context_dir[]; + + struct { + const char *name; + const char **dir; + } context_members_all[] = { + {"buttons", buttons_context_dir}, + {"clip", clip_context_dir}, + {"file", file_context_dir}, + {"image", image_context_dir}, + {"node", node_context_dir}, + {"screen", screen_context_dir}, + {"sequencer", sequencer_context_dir}, + {"text", text_context_dir}, + {"view3d", view3d_context_dir}, + }; + + PyObject *result = _PyDict_NewPresized(ARRAY_SIZE(context_members_all)); + for (int context_index = 0; context_index < ARRAY_SIZE(context_members_all); context_index++) { + const char *name = context_members_all[context_index].name; + const char **dir = context_members_all[context_index].dir; + int i; + for (i = 0; dir[i]; i++) { + /* Pass. */ + } + PyObject *members = PyTuple_New(i); + for (i = 0; dir[i]; i++) { + PyTuple_SET_ITEM(members, i, PyUnicode_FromString(dir[i])); + } + PyDict_SetItemString(result, name, members); + Py_DECREF(members); + } + BLI_assert(PyDict_GET_SIZE(result) == ARRAY_SIZE(context_members_all)); + + return result; +} + static PyMethodDef meth_bpy_script_paths = { "script_paths", (PyCFunction)bpy_script_paths, @@ -448,6 +504,12 @@ static PyMethodDef meth_bpy_unescape_identifier = { METH_O, bpy_unescape_identifier_doc, }; +static PyMethodDef meth_bpy_context_members = { + "context_members", + (PyCFunction)bpy_context_members, + METH_NOARGS, + bpy_context_members_doc, +}; static PyObject *bpy_import_test(const char *modname) { @@ -551,6 +613,9 @@ void BPy_init_modules(struct bContext *C) (PyObject *)PyCFunction_New(&meth_bpy_unescape_identifier, NULL)); PyModule_AddObject( mod, meth_bpy_flip_name.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_flip_name, NULL)); + PyModule_AddObject(mod, + meth_bpy_context_members.ml_name, + (PyObject *)PyCFunction_New(&meth_bpy_context_members, NULL)); /* register funcs (bpy_rna.c) */ PyModule_AddObject(mod, |