On the topic of duplication
I don't think this is a duplicate of the suggested post, although the contents of it may be helpful. The issue of converting an addon to run on Blender 4 is not going to be limited to one or two functions. The end state of this post will likely be a comparative selection of everything I end up changing, which might then be valuable as a reference for others.
This is going to be more of a journey than a singular question, because I don't really understand the problem at present, and it's been a while, so bear with me on this.
First step: understanding the problem.
I recently finally finished a serious milestone in my addon, getting it to Ver. 1.5, operating in Blender 2.93. And of course 2.93 is out of LTS now. This has been a long project. Anyway, rather than chasing after versions constantly I've decided to get out ahead of it and get this addon working in Blender 4 in the hopes of having it stable in time for whatever the LTS release will end up being.
My first obstacle: The init file to load my addon has a section to import the materials and other control scripts from the packaged .blend file. The last block of that section is:
context_c = context.copy()
context_c['edit_text'] = text_main
bpy.ops.text.run_script(context_c)
return {'FINISHED'}
Which now yields:
File "/home/misterl/.config/blender/4.0/scripts/addons/DIPSS/__init__.py", line 139, in execute
bpy.ops.text.run_script(context_c)
File "/home/misterl/Downloads/blender-4.0.2-linux-x64/4.0/scripts/modules/bpy/ops.py", line 106, in __call__
C_exec, C_undo = _BPyOpsSubModOp._parse_args(args)
File "/home/misterl/Downloads/blender-4.0.2-linux-x64/4.0/scripts/modules/bpy/ops.py", line 60, in _parse_args
raise ValueError("1-2 args execution context is supported")
ValueError: 1-2 args execution context is supported
A quick search here yields these questions:
Why does this tiny script not work in 4.0?
Which do tell me that BPY has changed, adding a different way to apply context, but doesn't really explain how I'm supposed to use the with command for context.
Specifically, I don't understand how I'm supposed to define the effective 'area' to assign context to.
Is it the area of code, or the window it's applied in?
https://docs.blender.org/api/current/bpy.ops.html#overriding-context
This page says:
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.
I wrote my code so that the import function would only work while an object is selected, and would then add the materials to that object. Easier that way.
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.
So do I need to make a new block of code to define the various contexts I'm using?
Update
I've been experimenting, and altering the code to this:
text_main= bpy.data.texts['menu_script.py']
# context_c = context.copy()
# context_c['edit_text'] = text_main
with bpy.context.temp_override:
bpy.ops.text.run_script(text_main)
return {'FINISHED'}
Yields a new error: AttributeError: __enter__
I've decided to split the loading into two parts. Still not sure how to have the first laoding go automatically, but I'll figure that out once I have a working button. For now I'm trying:
class WM_OT_Menu(Operator):
bl_label = "Load Menu"
bl_idname = "wm.load_menu"
with open(bpy.data.texts["menu_script.py"]):
bpy.ops.text.run_script(text_main)
break
But it doesn't load, it gives me: SyntaxError: 'break' outside loop
If I try it without break it gives me: TypeError: expected str, bytes or os.PathLike object, not Text
This:
class WM_OT_Menu(Operator):
bl_label = "Load Menu"
bl_idname = "wm.load_menu"
text_script = (bpy.data.texts["menu_script.py"])
bpy.ops.script.python_file_run(filepath=text_script)
Spits out: TypeError: Converting py args to operator properties: SCRIPT_OT_python_file_run.filepath expected a string type, not Text
So how am I supposed to tell this program what is a script?
Perusing the docs some more revealed another potential way to call a script:
class WM_OT_Menu(Operator):
bl_label = "Load Menu"
bl_idname = "wm.load_menu"
text_script = (bpy.data.texts["menu_script.py"])
bpy.ops.text.run_script(text_script)
And it's back to spitting out ValueError: 1-2 args execution context is supported
Update again
Further investigation has revealed a deeper issue in that the method I used to import scripts and materials from the packed .blend file in my addon no longer works.
I found this: https://developer.blender.org/docs/release_notes/4.0/python_api/ Which indicates there is a new system to do that, but like most of the documentation I've found this version, doesn't really tell me how I'm supposed to implement it. Going to play around with it and see what happens. Will update further if I make any discoveries.
I've discovered that some changes in the file handling system may be part of the problem here, specifically changing filename to filepath in certain contexts. This presents some challenges to the following:
class WM_OT_Main(Operator):
bl_label = "Load Procedural Systems"
bl_idname = "wm.load_main"
def execute(self, context):
if not bpy.data.materials.get("Skin"):
bpy.ops.wm.append(
filepath="Skin.blend",
directory=srcFile + skinmat,
filename="Skin",
set_fake=True)
Which as you can see uses both filename and filepath in a self contained block. This is the front of the import block I'm trying to fix, the rest of it is duplicates to call specific other materials and scripts.