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`).
This commit is contained in:
Campbell Barton
2023-10-31 20:59:10 +11:00
parent f2bb4c617f
commit ea86a77bc5
3 changed files with 38 additions and 7 deletions

View File

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

View File

@@ -986,9 +986,21 @@ def pymodule2sphinx(basepath, module_name, module, title, module_all_extra):
# `type_name` is only used for examples and messages:
# `<class 'bpy.app.handlers'>` -> `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("__"):