# What is the appropriate way to write and distribute an addon that works with both blender 2.80 and 2.79?

I have written a python addon which is compatible with both 2.79 and 2.80. When setting the "blender" key in bl_info to the appropriate version, the code works otherwise unmodified in both versions, without warnings.

Now I want to distribute this code as a zipped addon. I'd prefer not having to create two separate zips for exactly the same code.

However:

• If I set the bl_info "blender" key to (2, 79, 0), then blender 2.80 refuses to load it
• If I set it to (2, 80, 0), then blender 2.79 displays a warning cautioning the user that the module isn't intended for this blender version, and that it is likely to malfunction (although the module then happily runs without problems anyway). This is going to scare and confuse users of 2.79, see for example MHX2 import in 2.79 and 2.80?
• If I use a variable and try to calculate the appropriate blender version outside the bl_info block, then the zipped addon won't install at all, eventhough the same code runs just fine when the addon is manually extracted in either version's addons directory. It seems the install-addon-from-zip code manually cuts out the bl_info block and parses it out of context, causing it to fail when encountering a variable set outside the block.

So my question is: Is there a way to create and distribute a single addon zip file that works without warnings in both blender 2.79 and 2.80?

EDIT:

The code I used in option 3 (calculating a variable to determine the appropriate blender version is this:

import bpy
appver = (2, 80, 0)

if bpy.app.version < appver:
appver = (2, 79, 0)

bl_info = {
...
"blender": appver,
...
}


(which, as said, works fine when the addon is already unzipped, but crashes when trying to install from zip file)

The stack trace I get is this:

Traceback (most recent call last):
File "/home/joepal/system/blender-2.80-d40bffa17f6-linux-glibc224-x86_64/2.80/scripts/modules/addon_utils.py", line 137, in fake_module
mod.bl_info = ast.literal_eval(body.value)
File "/home/joepal/system/blender-2.80-d40bffa17f6-linux-glibc224-x86_64/2.80/python/lib/python3.7/ast.py", line 91, in literal_eval
return _convert(node_or_string)
File "/home/joepal/system/blender-2.80-d40bffa17f6-linux-glibc224-x86_64/2.80/python/lib/python3.7/ast.py", line 79, in _convert
map(_convert, node.values)))
File "/home/joepal/system/blender-2.80-d40bffa17f6-linux-glibc224-x86_64/2.80/python/lib/python3.7/ast.py", line 90, in _convert
return _convert_signed_num(node)
File "/home/joepal/system/blender-2.80-d40bffa17f6-linux-glibc224-x86_64/2.80/python/lib/python3.7/ast.py", line 63, in _convert_signed_num
return _convert_num(node)
File "/home/joepal/system/blender-2.80-d40bffa17f6-linux-glibc224-x86_64/2.80/python/lib/python3.7/ast.py", line 55, in _convert_num
raise ValueError('malformed node or string: ' + repr(node))
ValueError: malformed node or string: <_ast.Name object at 0x7fb74bd55780>
Traceback (most recent call last):
File "/home/joepal/system/blender-2.80-d40bffa17f6-linux-glibc224-x86_64/2.80/scripts/startup/bl_operators/wm.py", line 2042, in execute
File "/home/joepal/system/blender-2.80-d40bffa17f6-linux-glibc224-x86_64/2.80/scripts/modules/addon_utils.py", line 208, in modules
modules_refresh(module_cache)
File "/home/joepal/system/blender-2.80-d40bffa17f6-linux-glibc224-x86_64/2.80/scripts/modules/addon_utils.py", line 195, in modules_refresh
force_support=force_support,
File "/home/joepal/system/blender-2.80-d40bffa17f6-linux-glibc224-x86_64/2.80/scripts/modules/addon_utils.py", line 137, in fake_module
mod.bl_info = ast.literal_eval(body.value)
File "/home/joepal/system/blender-2.80-d40bffa17f6-linux-glibc224-x86_64/2.80/python/lib/python3.7/ast.py", line 91, in literal_eval
return _convert(node_or_string)
File "/home/joepal/system/blender-2.80-d40bffa17f6-linux-glibc224-x86_64/2.80/python/lib/python3.7/ast.py", line 79, in _convert
map(_convert, node.values)))
File "/home/joepal/system/blender-2.80-d40bffa17f6-linux-glibc224-x86_64/2.80/python/lib/python3.7/ast.py", line 90, in _convert
return _convert_signed_num(node)
File "/home/joepal/system/blender-2.80-d40bffa17f6-linux-glibc224-x86_64/2.80/python/lib/python3.7/ast.py", line 63, in _convert_signed_num
return _convert_num(node)
File "/home/joepal/system/blender-2.80-d40bffa17f6-linux-glibc224-x86_64/2.80/python/lib/python3.7/ast.py", line 55, in _convert_num
raise ValueError('malformed node or string: ' + repr(node))
ValueError: malformed node or string: <_ast.Name object at 0x7fb74bd55780>

• i would lean to moving forward and have a version of each, a branch on git does this for example. The choice then is which is master branch. On what you tried.. Can you provide an example of your "variable outside bl_info block" ? Does it fail in addon_utils fake_module by any chance ? – batFINGER Jan 1 at 14:48
• Edited to add info about what went wrong in the approach with trying to use a calculated blender version. @batFINGER: Having different branches would in effect mean distributing separate zip files with the same code. The question I'm asking is if it's possible to avoid doing that. If the answer to the question is "no" then, yes, keeping separate branches would be the logical thing to do. – Joel Palmius Jan 1 at 21:45