From ea86a77bc53eb5ff14aeee2235bc36e79f87ed8d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 31 Oct 2023 20:59:10 +1100 Subject: [PATCH] Docs: add notes on populating bpy.app.driver_namespace Address issues raised by #114155. Also fix sphinx documentation generation using incorrect identifiers when looking up references from PyStruct types (was looking for `bpy.app.bpy.app.driver_namespace.py`). --- .../examples/bpy.app.driver_namespace.py | 19 +++++++++++++++++++ doc/python_api/sphinx_doc_gen.py | 14 +++++++++++++- source/blender/python/intern/bpy_app.cc | 12 ++++++------ 3 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 doc/python_api/examples/bpy.app.driver_namespace.py diff --git a/doc/python_api/examples/bpy.app.driver_namespace.py b/doc/python_api/examples/bpy.app.driver_namespace.py new file mode 100644 index 00000000000..0b5b2f6ea4b --- /dev/null +++ b/doc/python_api/examples/bpy.app.driver_namespace.py @@ -0,0 +1,19 @@ +""" +File Loading & Order of Initialization + Since drivers are evaluated immediately after loading a blend-file, + using ``--python`` to populate name-space often fails to achieve the desired goal because the initial evaluation + will lookup a function that doesn't exist yet, marking the driver as invalid - preventing further evaluation. + + Populating the driver name-space before the blend-file loads also doesn't work + since opening a file clears the name-space. + + The driver name-space should be populated for newly loaded files using text-block registration. + + Text blocks may be marked to execute on startup from the text editor *Text -> Register*. + Scripts that are registered will execute after a blend-file loads & before driver evaluation. + + It's also possible to use run a script via the ``--python`` command line argument, before the blend file. + This can register a load-post handler (:mod:`bpy.app.handlers.load_post`) that initialized the name-space. + While this works for background tasks it has the downside that opening the file from the file selector + won't setup the name-space. +""" diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index c418d20cc07..adb6f3117f2 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -986,9 +986,21 @@ def pymodule2sphinx(basepath, module_name, module, title, module_all_extra): # `type_name` is only used for examples and messages: # `` -> `bpy.app.handlers`. type_name = str(type(module)).strip("<>").split(" ", 1)[-1][1:-1] + + # The type typically contains the module in the case of PyStruct's (defined by Blender). + # Assign a temporary module name: `module_name_split`. + if module_name == type_name: + assert "." in module_name + module_name_split, type_name = module_name.rpartition(".")[0::2] + elif type_name.startswith(module_name + "."): + type_name = type_name.removeprefix(module_name + ".") + else: + module_name_split = module_name + if type(descr) == types.GetSetDescriptorType: - py_descr2sphinx("", fw, descr, module_name, type_name, key) + py_descr2sphinx("", fw, descr, module_name_split, type_name, key) attribute_set.add(key) + del module_name_split descr_sorted = [] for key, descr in sorted(type(module).__dict__.items()): if key.startswith("__"): diff --git a/source/blender/python/intern/bpy_app.cc b/source/blender/python/intern/bpy_app.cc index d833ec277c4..8de87fba1be 100644 --- a/source/blender/python/intern/bpy_app.cc +++ b/source/blender/python/intern/bpy_app.cc @@ -220,9 +220,9 @@ static PyObject *make_app_info() /* a few getsets because it makes sense for them to be in bpy.app even though * they are not static */ -PyDoc_STRVAR( - bpy_app_debug_doc, - "Boolean, for debug info (started with --debug / --debug_* matching this attribute name)"); +PyDoc_STRVAR(bpy_app_debug_doc, + "Boolean, for debug info " + "(started with ``--debug`` / ``--debug-*`` matching this attribute name)"); static PyObject *bpy_app_debug_get(PyObject * /*self*/, void *closure) { const int flag = POINTER_AS_INT(closure); @@ -249,9 +249,9 @@ static int bpy_app_debug_set(PyObject * /*self*/, PyObject *value, void *closure return 0; } -PyDoc_STRVAR( - bpy_app_global_flag_doc, - "Boolean, for application behavior (started with --enable-* matching this attribute name)"); +PyDoc_STRVAR(bpy_app_global_flag_doc, + "Boolean, for application behavior " + "(started with ``--enable-*`` matching this attribute name)"); static PyObject *bpy_app_global_flag_get(PyObject * /*self*/, void *closure) { const int flag = POINTER_AS_INT(closure);