4

In Blender versions before 4.0, I would execute text blocks with the following Python code.

# Retrieve the text file
rig_file = bpy.data.texts["hello.py"]
rig_text = rig_file.as_string()

Modify text string as needed here ...

Execute the script

ctx = bpy.context.copy() ctx['edit_text'] = rig_file bpy.ops.text.run_script(ctx)

This worked flawlessly in 3.6. Now in 4.0, passing in context overrides has been depricated in favor of Context.temp_override.

How would I execute this code in 4.0 and beyond? I know it would have to be in the syntax of the temp_override, but what do I pass in to the with block to make this work?

# [4.0] Execute the script
ctx = bpy.context.copy()
ctx['edit_text'] = rig_file
with bpy.context.temp_override(): # What do I pass in?
     bpy.ops.text.run_script() # Is this still correct in 4.0?

Edit: For convenience I'll post the documentation on text operators: https://docs.blender.org/api/current/bpy.ops.text.html You will notice that run_script() doesn't take in anything anymore, and that it is described as running the 'active script'. The question is, how do I set my text file as the active script to run?

OctavoPE
  • 73
  • 5

2 Answers2

2

Figured it out. We pass in edit_text.

So our complete code block now is:

# Retrieve the text file
rig_file = bpy.data.texts["hello.py"]
rig_text = rig_file.as_string()

Modify text string as needed here ...

[4.0] Execute the script

ctx = bpy.context.copy() ctx['edit_text'] = rig_file with bpy.context.temp_override(edit_text=rig_file): bpy.ops.text.run_script()

OctavoPE
  • 73
  • 5
  • Thanks for sharing. For reference I added it to https://blender.stackexchange.com/questions/248274/a-comprehensive-list-of-operator-overrides – Gorgious Jan 17 '24 at 09:53
  • @Gorgious That is amazing documentation. Thank you for your hard work. – OctavoPE Jan 17 '24 at 17:21
2

There's also an alternative operator-less way to run a text block - as_module()

>>> with C.temp_override(edit_text = D.texts['A']):
...     bpy.ops.text.run_script()
...     
a
{'FINISHED'}

>>> D.texts['A'].as_module() a <module 'A' from 'A'>

The advantage of that is that you can call functions within that module:

>>> module_A = D.texts['A'].as_module()
a

>>> module_A.multiply_by_3( multiply_by_3(number_to_multiply) >>> module_A.multiply_by_3(6) 18

To clarify, that's the contents of the "A" Text Block:

print("a")

def multiply_by_3(number_to_multiply): return number_to_multiply*3

How to import text data blocks as modules using the 'from/import' statement?

Markus von Broady
  • 36,563
  • 3
  • 30
  • 99