The reasoning here is to decouple the actual code from the manifest aka meta data.
That way, tooling can be made much simpler by just replacing the existing meta data without having to wade through the existing _init_.py code, which in turn can be arbitrarily complex and with bl_info located in arbitrary positions in the code.
My proposal would be to include a manifest.py or bl_info.py file with each addon, along with its main entry point, which is _init_.py.
Or better yet, make it a json or yaml file so that we can use arbitrary build systems, not necessarily aware of python, or having to write out python where the most native/naive solution would be json or yaml.
Ideally, however, the manifest will be interpreted dynamically, so that we can read the data from a VERSION_INFO file in the addon, from where we will fill out the blanks in the bl_info, say, documentation link that will link to a specific version and changelog thereof and a warning that is based on the current release state and whatnot. Which again will reduce our tooling overhead during ci builds to a minimum as it is all in code and we would just replace the VERSION_INFO file.
However, the specifics are unknown to blender and it will just interpret the manifest and get the bl_info export from that module.
For now I have settled on a solution in _init_.py that will work, but it feels a bit off, especially with blender first parsing the bl_info structure and with blender version initially being 0.0.0 and the plugin version initially being 0.0.0, both of which are to be replaced later on. However, this will break blender from performing any version checks, so disabling the addon might fail due to a version mismatch.
bl_info = {
'name': 'Foobar',
'author': 'Some Foe',
'description': '',
'support': 'COMMUNITY',
'location': 'View3D > Sidebar > Foobar',
'wiki_url': '...'
'tracker_url': '...',
'category': 'Some Category',
'version': (0, 0, 0),
'warning': '',
'blender': (0, 0, 0),
# 'version': will be filled in later
# 'warning': will be filled in later
# 'blender': will be filled in later
# 'wiki_url': will be filled in later
# 'tracker_url': will be filled in later
}
import addon_utils
from .utils.addon import load_version, version_warning
version = load_version(os.path.dirname(os.path.realpath(__file__)))
def find_addon_info(name):
for addon in addon_utils.modules():
if addon.bl_info['name'] == name:
return addon.bl_info
return None
addon_bl_info = find_addon_info(bl_info['name'])
addon_bl_info['version'] = version.to_tuple()
addon_bl_info['warning'] = version_warning(version)
addon_bl_info['blender'] = (2, 93, 0)
addon_bl_info['wiki_url'] = 'https://example.org'
addon_bl_info['tracker_url'] = 'https://example.org'