From 09a2b5c70f7607ce27eaa1f63cc359dd71b3b06e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 21 Apr 2023 20:30:55 +1000 Subject: [PATCH] Docs: note that renaming data-blocks sorted them which impacts iteration Address issue raised in #107027. --- doc/python_api/rst/info_gotcha.rst | 43 +++++++++++++++++++----------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/doc/python_api/rst/info_gotcha.rst b/doc/python_api/rst/info_gotcha.rst index e2a49898a4b..bb4fce7d579 100644 --- a/doc/python_api/rst/info_gotcha.rst +++ b/doc/python_api/rst/info_gotcha.rst @@ -865,29 +865,40 @@ Unfortunate Corner Cases Besides all expected cases listed above, there are a few others that should not be an issue but, due to internal implementation details, currently are: -- ``Object.hide_viewport``, ``Object.hide_select`` and ``Object.hide_render``: - Setting any of those Booleans will trigger a rebuild of Collection caches, - thus breaking any current iteration over ``Collection.all_objects``. + +Collection Objects +^^^^^^^^^^^^^^^^^^ + +Changing: ``Object.hide_viewport``, ``Object.hide_select`` or ``Object.hide_render`` +will trigger a rebuild of Collection caches, thus breaking any current iteration over ``Collection.all_objects``. + + .. rubric:: Do not: + + .. code-block:: python + + # `all_objects` is an iterator. Using it directly while performing operations on its members that will update + # the memory accessed by the `all_objects` iterator will lead to invalid memory accesses and crashes. + for object in bpy.data.collections["Collection"].all_objects: + object.hide_viewport = True -.. rubric:: Do not: + .. rubric:: Do: -.. code-block:: python + .. code-block:: python - # `all_objects` is an iterator. Using it directly while performing operations on its members that will update - # the memory accessed by the `all_objects` iterator will lead to invalid memory accesses and crashes. - for object in bpy.data.collections["Collection"].all_objects: - object.hide_viewport = True + # `all_objects[:]` is an independent list generated from the iterator. As long as no objects are deleted, + # its content will remain valid even if the data accessed by the `all_objects` iterator is modified. + for object in bpy.data.collections["Collection"].all_objects[:]: + object.hide_viewport = True -.. rubric:: Do: +Data-Blocks Renaming During Iteration +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. code-block:: python - - # `all_objects[:]` is an independent list generated from the iterator. As long as no objects are deleted, - # its content will remain valid even if the data accessed by the `all_objects` iterator is modified. - for object in bpy.data.collections["Collection"].all_objects[:]: - object.hide_viewport = True +Data-blocks accessed from ``bpy.data`` are sorted when their name is set. +Any loop that iterates of a data such as ``bpy.data.objects`` for example, +and sets the objects ``name`` must get all items from the iterator first (typically by converting to a list or tuple) +to avoid missing some objects and iterating over others multiple times. sys.exit