1

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?

`ValueError: 1-2 args execution context is supported` on call to `bpy.ops.outliner.show_hierarchy` in Blender 4.0.1

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.

  • 1
    yes, the context override has been changed in one of the 3.x version. The "__enter__" error is a Python error related to the "with" statement. Have a look here: https://stackoverflow.com/questions/51427729/python-error-attributeerror-enter – Blunder Feb 29 '24 at 18:44
  • also check out https://blender.stackexchange.com/questions/248274/a-comprehensive-list-of-operator-overrides – Gorgious Mar 01 '24 at 06:31
  • Hello, Mr.L.. please let us know if your problem has been solved in the comments, so we can close this out as a duplicate, if that is the case. If not, then an edit to explain why not woul help move things along. Thanks. – Robin Betts Mar 01 '24 at 07:49
  • Is this a duplicate? I haven't seen any other questions on this. It's definitely not solved yet. – MisterLBlends Mar 02 '24 at 18:50
  • 1
    The answer to your question is simple: "go through change logs between the two versions and apply all changes to your code". Of course I'm not writing an answer like this because it would be rudely contrasting with the current length of the question. I think this hints the question doesn't satisfy the SE rules: it needs more focus. To (only slightly!) exaggerate: imagine a question "How do you fix bugs in code?" BSE is a bad place for such comprehensive subjects because of its structure and 30k character limit. – Markus von Broady Mar 02 '24 at 20:12
  • I've been reading the changelogs and and the API docs, they don't actually compare the changes very well, partly because a lot of stuff has just been removed so the new way to do things has nothing to do with the old way. And the API doesn't have many examples for how to structure the new functions. I'm trying to understand why the problems exist and I don't have much to go on besides "It's different now." – MisterLBlends Mar 02 '24 at 20:17
  • @MisterLBlends and each such specific case is a good material for a BSE question, e.g. "face maps have been removed now and replaced by attributes" is a good starting point to write a question "How do I reimplement face maps functionality in Blender 4?" – Markus von Broady Mar 02 '24 at 20:22
  • Are you telling me it would be better to break this up into several questions? "How do I append a file with python on B4?" "How do I append a material with python in B4?" "How do I make a button run a script to append a file in Blender 4?" – MisterLBlends Mar 02 '24 at 20:24
  • Yea, I guess. Though I think a proper course of action might be to mark as a duplicate of a question with similar title but without "Blender 4", and incentivizing writing a new answer under the old question. Or you could directly write a comment under such an old question (if you discover it). On 2nd thoughts my example of a question might be bad, because it looks like XY problem, but when porting code you don't necessarily want to redesign the code and you're looking for the most direct translations of idioms... Maybe worth opening a question about that on meta... – Markus von Broady Mar 02 '24 at 20:40
  • I have been going around and finding such questions and asking 'what do now?'. Haven't had any responses yet. And yeah that's how this started. It threw up an error at the run code, but then I later discovered the append script wasn't even working. It's like unravelling a rat's nest. I'm going to have to consider this, I might end up breaking it up into multiples on Monday if I can't find a solution. – MisterLBlends Mar 02 '24 at 20:45
  • The linked question did eventually solve the problem I started with, though it took me a while to figure that out. I will start a more specific question about the appending problem, as I haven't seen anyone even talking about that. – MisterLBlends Mar 02 '24 at 21:09
  • regarding this: text_script = (bpy.data.texts["menu_script.py"]) bpy.ops.text.run_script(text_script) -> try this: text_script.as_string() – Chris Mar 05 '24 at 04:35

0 Answers0