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.
This commit is contained in:
Campbell Barton 2022-05-18 16:59:16 +10:00
parent 88fbe94d70
commit c8edc458d1
Notes: blender-bot 2023-06-21 19:23:24 +02:00
Referenced by commit f937c186de, Fix build error on WIN32 from `_bpy.context_members`
2 changed files with 72 additions and 26 deletions

View File

@ -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

View File

@ -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,