Fix T70481: Segfault printing 'private data' evaluated IDs.
authorBastien Montagne <montagne29@wanadoo.fr>
Fri, 4 Oct 2019 10:24:26 +0000 (12:24 +0200)
committerBastien Montagne <montagne29@wanadoo.fr>
Fri, 4 Oct 2019 10:27:10 +0000 (12:27 +0200)
This commit solves the bug itself (code was broken when real_id owner of
the private data ID could not be found), and generates a more sensible
representation for all evaluated IDs, makes no sense to display them as
being part of `bpy.data....`!

source/blender/python/intern/bpy_rna.c

index 45a7d2dacd1f6061959b71ef3e066ebcbedb90fa..d13393280d036af6692a91e98d58f52ae3ec4e08 100644 (file)
@@ -70,6 +70,8 @@
 /* Only for types. */
 #include "BKE_node.h"
 
+#include "DEG_depsgraph_query.h"
+
 #include "../generic/idprop_py_api.h" /* For IDprop lookups. */
 #include "../generic/py_capi_utils.h"
 #include "../generic/python_utildefines.h"
@@ -918,7 +920,10 @@ static PyObject *pyrna_struct_repr(BPy_StructRNA *self)
 
   tmp_str = PyUnicode_FromString(id->name + 2);
 
-  if (RNA_struct_is_ID(self->ptr.type) && (id->flag & LIB_PRIVATE_DATA) == 0) {
+  if (DEG_get_original_id(id) != id) {
+    ret = PyUnicode_FromFormat("Evaluated %s %R", BKE_idcode_to_name(GS(id->name)), tmp_str);
+  }
+  else if (RNA_struct_is_ID(self->ptr.type) && (id->flag & LIB_PRIVATE_DATA) == 0) {
     ret = PyUnicode_FromFormat(
         "bpy.data.%s[%R]", BKE_idcode_to_name_plural(GS(id->name)), tmp_str);
   }
@@ -926,14 +931,25 @@ static PyObject *pyrna_struct_repr(BPy_StructRNA *self)
     const char *path;
     ID *real_id = NULL;
     path = RNA_path_from_real_ID_to_struct(G_MAIN, &self->ptr, &real_id);
-    if (path) {
-      if (real_id != id) {
+    if (path != NULL) {
+      /* real_id may be NULL in some cases, although the only valid one is evaluated data,
+       * which should have been catched already above.
+       * So assert, but handle it without crashing for release builds. */
+      BLI_assert(real_id != NULL);
+
+      if (real_id != NULL) {
         Py_DECREF(tmp_str);
         tmp_str = PyUnicode_FromString(real_id->name + 2);
+        ret = PyUnicode_FromFormat(
+            "bpy.data.%s[%R].%s", BKE_idcode_to_name_plural(GS(real_id->name)), tmp_str, path);
+      }
+      else {
+        /* Can't find the path, print something useful as a fallback. */
+        ret = PyUnicode_FromFormat("bpy.data.%s[%R]...%s",
+                                   BKE_idcode_to_name_plural(GS(id->name)),
+                                   tmp_str,
+                                   RNA_struct_identifier(self->ptr.type));
       }
-      ret = PyUnicode_FromFormat(
-          "bpy.data.%s[%R].%s", BKE_idcode_to_name_plural(GS(real_id->name)), tmp_str, path);
-
       MEM_freeN((void *)path);
     }
     else {