[Bf-blender-cvs] [a80c1e5] master: Fix T44822: python enums' itemf callback did not handle 'NULL' context case.

Bastien Montagne noreply at git.blender.org
Mon May 25 14:28:50 CEST 2015


Commit: a80c1e50bc7f57bc4d4c41bc51ac92d1d4c39030
Author: Bastien Montagne
Date:   Mon May 25 14:19:51 2015 +0200
Branches: master
https://developer.blender.org/rBa80c1e50bc7f57bc4d4c41bc51ac92d1d4c39030

Fix T44822: python enums' itemf callback did not handle 'NULL' context case.

Enum's itemf callback can be called without context in some cases (UI, doc generation...).
Python's enum properties did not handle this at all - it's kind of odd this did not cause
more trouble and wasn't notice earlier... Probably dynamic enums using context are not
much used in py code.

Note about nodes: those are heavy users of dynamic enum with context. Now,
we expect `NodeCategory.poll()` and `NodeItem.poll()` to always be called with
a valid context (since when there is no context available, we can assume `poll()`
is always True). `NodeCategory.items()`, however, must accept NULL context, so if
you use custom `items` callable for your custom node categories, you may need
to update it (as was done here for builtin `node_group_items()`).

===================================================================

M	release/scripts/modules/nodeitems_utils.py
M	release/scripts/startup/nodeitems_builtins.py
M	release/scripts/templates_py/ui_previews_dynamic_enum.py
M	source/blender/python/intern/bpy_props.c

===================================================================

diff --git a/release/scripts/modules/nodeitems_utils.py b/release/scripts/modules/nodeitems_utils.py
index 2882a08..ff21009 100644
--- a/release/scripts/modules/nodeitems_utils.py
+++ b/release/scripts/modules/nodeitems_utils.py
@@ -37,7 +37,7 @@ class NodeCategory:
         else:
             def items_gen(context):
                 for item in items:
-                    if item.poll is None or item.poll(context):
+                    if item.poll is None or context is None or item.poll(context):
                         yield item
             self.items = items_gen
 
@@ -136,7 +136,7 @@ def register_node_categories(identifier, cat_list):
 def node_categories_iter(context):
     for cat_type in _node_categories.values():
         for cat in cat_type[0]:
-            if cat.poll and cat.poll(context):
+            if cat.poll and ((context is None) or cat.poll(context)):
                 yield cat
 
 
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index 98c524b..bee48de 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -66,6 +66,8 @@ node_tree_group_type = {
 
 # generic node group items generator for shader, compositor and texture node groups
 def node_group_items(context):
+    if context is None:
+        return
     space = context.space_data
     if not space:
         return
diff --git a/release/scripts/templates_py/ui_previews_dynamic_enum.py b/release/scripts/templates_py/ui_previews_dynamic_enum.py
index 5269f7f..5169b82 100644
--- a/release/scripts/templates_py/ui_previews_dynamic_enum.py
+++ b/release/scripts/templates_py/ui_previews_dynamic_enum.py
@@ -25,9 +25,12 @@ import bpy
 
 def enum_previews_from_directory_items(self, context):
     """EnumProperty callback"""
-    wm = context.window_manager
-
     enum_items = []
+
+    if context is None:
+        return enum_items
+
+    wm = context.window_manager
     directory = wm.my_previews_dir
 
     # Get the preview collection (defined in register func).
diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c
index 779c738..b0fae24 100644
--- a/source/blender/python/intern/bpy_props.c
+++ b/source/blender/python/intern/bpy_props.c
@@ -1481,15 +1481,26 @@ static EnumPropertyItem *bpy_prop_enum_itemf_cb(struct bContext *C, PointerRNA *
 	EnumPropertyItem *eitems = NULL;
 	int err = 0;
 
-	bpy_context_set(C, &gilstate);
+	if (C) {
+		bpy_context_set(C, &gilstate);
+	}
+	else {
+		gilstate = PyGILState_Ensure();
+	}
 
 	args = PyTuple_New(2);
 	self = pyrna_struct_as_instance(ptr);
 	PyTuple_SET_ITEM(args, 0, self);
 
 	/* now get the context */
-	PyTuple_SET_ITEM(args, 1, (PyObject *)bpy_context_module);
-	Py_INCREF(bpy_context_module);
+	if (C) {
+		PyTuple_SET_ITEM(args, 1, (PyObject *)bpy_context_module);
+		Py_INCREF(bpy_context_module);
+	}
+	else {
+		PyTuple_SET_ITEM(args, 1, Py_None);
+		Py_INCREF(Py_None);
+	}
 
 	items = PyObject_CallObject(py_func, args);
 
@@ -1530,8 +1541,13 @@ static EnumPropertyItem *bpy_prop_enum_itemf_cb(struct bContext *C, PointerRNA *
 		eitems = DummyRNA_NULL_items;
 	}
 
+	if (C) {
+		bpy_context_clear(C, &gilstate);
+	}
+	else {
+		PyGILState_Release(gilstate);
+	}
 
-	bpy_context_clear(C, &gilstate);
 	return eitems;
 }
 
@@ -2618,7 +2634,7 @@ PyDoc_STRVAR(BPy_EnumProperty_doc,
 "      Note the item is optional.\n"
 "      For dynamic values a callback can be passed which returns a list in\n"
 "      the same format as the static list.\n"
-"      This function must take 2 arguments (self, context)\n"
+"      This function must take 2 arguments (self, context), **context may be None**.\n"
 "      WARNING: There is a known bug with using a callback,\n"
 "      Python must keep a reference to the strings returned or Blender will crash.\n"
 "   :type items: sequence of string tuples or a function\n"




More information about the Bf-blender-cvs mailing list