2
$\begingroup$

I'm working on an add-on which generates a script. I want this script to be loaded in the Blender space and eventually launched. But I can't override the context correctly.

The documentation doesn't clarify much. I'm following this code example, which works as expected.

If we run from the console bpy.context.copy() we obtain a list of "states", I think I should override one of those with the correct one. But by guessing it's impossible. Can someone help?

override = bpy.context.copy()
override['space_data'] = bpy.data.texts['text_to_run.py']
with bpy.context.temp_override(**override):
    bpy.ops.text.reload()
$\endgroup$
1

1 Answer 1

5
$\begingroup$

https://docs.blender.org/api/current/bpy.ops.html#overriding-context Seems to clarify enough:

Overriding Context

It is possible to override context members that the operator sees, so that they act on specified rather than the selected or active data, or to execute an operator in the different part of the user interface.

The context overrides are passed as a dictionary, with keys matching the context member names in bpy.context. For example to override bpy.context.active_object, you would pass {'active_object': object} to bpy.types.Context.temp_override.

Note

You will nearly always want to use a copy of the actual current context as basis (otherwise, you’ll have to find and gather all needed data yourself).

# Remove all objects in scene rather than the selected ones.
import bpy
from bpy import context
override = context.copy()
override["selected_objects"] = list(context.scene.objects)
with context.temp_override(**override):
    bpy.ops.object.delete()

So... we don't know what context should be used. Luckily that context is right when a script is run from text editor so if I just print current context with a script in the text editor that's the right context:

import bpy

current_context = bpy.context.copy()
print(current_context) 

That gives me this in Blender's system console:

{'active_annotation_layer': None, 'active_bone': None, 'active_editable_fcurve': None, 'active_gpencil_frame': None, 'active_gpencil_layer': None, 'active_nla_strip': None, 'active_nla_track': None, 'active_object': None, 'active_operator': None, 'active_pose_bone': None, 'active_sequence_strip': None, 'annotation_data': None, 'annotation_data_owner': None, 'area': bpy.data.screens['Layout']...Area, 'asset_file_handle': None, 'asset_library_ref': bpy.data.workspaces['Main']...AssetLibraryReference, 'blend_data': <bpy_struct, BlendData at 0x0000026E1ED44108>, 'collection': bpy.data.collections['Main'], 'edit_object': None, 'edit_text': bpy.data.texts['Text'], 'editable_bones': None, 'editable_fcurves': None, 'editable_gpencil_layers': None, 'editable_gpencil_strokes': None, 'editable_objects': [], 'engine': 'CYCLES', 'evaluated_depsgraph_get': <bpy_func Context.evaluated_depsgraph_get()>, 'gizmo_group': None, 'gpencil_data': None, 'gpencil_data_owner': None, 'image_paint_object': None, 'layer_collection': bpy.data.scenes['Scene']...LayerCollection, 'mode': 'OBJECT', 'object': None, 'objects_in_mode': [], 'objects_in_mode_unique_data': [], 'particle_edit_object': None, 'pose_object': None, 'preferences': <bpy_struct, Preferences at 0x00007FF628D8D8E0>, 'region': bpy.data.screens['Layout']...Region, 'region_data': None, 'scene': bpy.data.scenes['Scene'], 'screen': bpy.data.screens['Layout'], 'sculpt_object': None, 'selectable_objects': [], 'selected_bones': None, 'selected_editable_actions': None, 'selected_editable_bones': None, 'selected_editable_fcurves': None, 'selected_editable_keyframes': None, 'selected_editable_objects': [], 'selected_editable_sequences': [], 'selected_movieclip_tracks': None, 'selected_nla_strips': None, 'selected_objects': [], 'selected_pose_bones': None, 'selected_pose_bones_from_active_object': None, 'selected_sequences': [], 'selected_visible_actions': None, 'selected_visible_fcurves': None, 'sequences': [], 'space_data': bpy.data.screens['Layout']...SpaceTextEditor, 'tool_settings': bpy.data.scenes['Scene'].tool_settings, 'ui_list': None, 'vertex_paint_object': None, 'view_layer': bpy.data.scenes['Scene'].view_layers["View Layer"], 'visible_bones': None, 'visible_fcurves': None, 'visible_gpencil_layers': None, 'visible_objects': [], 'visible_pose_bones': None, 'weight_paint_object': None, 'window': bpy.data.scenes['Scene']...Window, 'window_manager': bpy.data.window_managers['WinMan'], 'workspace': bpy.data.workspaces['Main']} 

OK, so let's look for something interesting there. It's probably none of the stuff that is None... so I ignore that and look through all the other stuff and here it is 'edit_text': bpy.data.texts['Text'] - now that looks really interesting. Let's try that:

import bpy
from bpy import context
override = context.copy()
override["edit_text"] =  bpy.data.texts['script_to_run.py']
with context.temp_override(**override):
    bpy.ops.text.run_script()

And it works! That's it.

$\endgroup$
3
  • $\begingroup$ Thank you! I had already tied that, but with the bpy.ops.text.reload() It results in a bad crash to the desktop... now I noticed that without the reload the override works.. I would like to understand why. $\endgroup$
    – Lucho
    Commented Sep 1, 2022 at 9:34
  • $\begingroup$ So would this potentially work to for a button in the 3D view window that runs a script to import other scripts and materials from an addon? That's the challenge I'm currently facing here: blender.stackexchange.com/q/313862/149985 $\endgroup$ Commented Mar 2 at 18:55
  • $\begingroup$ @MisterLBlends No idea. If you don't provide the full code you run, there is no way to tell. Go through change logs between the two versions and apply all changes to your code like Markus von Broady suggested in the comments on your linked question. $\endgroup$ Commented Mar 3 at 8:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .