If bpy fails to import, assume we are in subprocess and only import subproc.py
This commit is contained in:
@@ -42,17 +42,22 @@ else:
|
|||||||
from . import utils
|
from . import utils
|
||||||
from .bpkg import Package
|
from .bpkg import Package
|
||||||
|
|
||||||
import bpy
|
try:
|
||||||
from collections import OrderedDict
|
import bpy
|
||||||
import multiprocessing
|
except ImportError:
|
||||||
|
from . import subproc
|
||||||
|
else:
|
||||||
|
|
||||||
mp_context = multiprocessing.get_context()
|
from collections import OrderedDict
|
||||||
mp_context.set_executable(bpy.app.binary_path_python)
|
import multiprocessing
|
||||||
|
|
||||||
# global list of all known packages, indexed by name
|
mp_context = multiprocessing.get_context()
|
||||||
_packages = OrderedDict()
|
mp_context.set_executable(bpy.app.binary_path_python)
|
||||||
|
|
||||||
class ConsolidatedPackage:
|
# global list of all known packages, indexed by name
|
||||||
|
_packages = OrderedDict()
|
||||||
|
|
||||||
|
class ConsolidatedPackage:
|
||||||
"""
|
"""
|
||||||
Stores a grouping of different versions of the same package
|
Stores a grouping of different versions of the same package
|
||||||
"""
|
"""
|
||||||
@@ -114,7 +119,7 @@ class ConsolidatedPackage:
|
|||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return (pkg for pkg in self.versions)
|
return (pkg for pkg in self.versions)
|
||||||
|
|
||||||
class SubprocMixin:
|
class SubprocMixin:
|
||||||
"""Mix-in class for things that need to be run in a subprocess."""
|
"""Mix-in class for things that need to be run in a subprocess."""
|
||||||
|
|
||||||
log = logging.getLogger(__name__ + '.SubprocMixin')
|
log = logging.getLogger(__name__ + '.SubprocMixin')
|
||||||
@@ -242,7 +247,7 @@ class SubprocMixin:
|
|||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
class PACKAGE_OT_install(SubprocMixin, bpy.types.Operator):
|
class PACKAGE_OT_install(SubprocMixin, bpy.types.Operator):
|
||||||
bl_idname = 'package.install'
|
bl_idname = 'package.install'
|
||||||
bl_label = 'Install package'
|
bl_label = 'Install package'
|
||||||
bl_description = 'Downloads and installs a Blender add-on package'
|
bl_description = 'Downloads and installs a Blender add-on package'
|
||||||
@@ -322,7 +327,7 @@ class PACKAGE_OT_install(SubprocMixin, bpy.types.Operator):
|
|||||||
self.log.error('Process died without telling us! Exit code was 0 though')
|
self.log.error('Process died without telling us! Exit code was 0 though')
|
||||||
self.report({'WARNING'}, 'Error downloading package, but process finished OK. This is weird.')
|
self.report({'WARNING'}, 'Error downloading package, but process finished OK. This is weird.')
|
||||||
|
|
||||||
class PACKAGE_OT_uninstall(SubprocMixin, bpy.types.Operator):
|
class PACKAGE_OT_uninstall(SubprocMixin, bpy.types.Operator):
|
||||||
bl_idname = 'package.uninstall'
|
bl_idname = 'package.uninstall'
|
||||||
bl_label = 'Install package'
|
bl_label = 'Install package'
|
||||||
bl_description = "Remove installed package files from filesystem"
|
bl_description = "Remove installed package files from filesystem"
|
||||||
@@ -381,12 +386,12 @@ class PACKAGE_OT_uninstall(SubprocMixin, bpy.types.Operator):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_packages_from_disk(refresh=False) -> list:
|
def get_packages_from_disk(refresh=False) -> list:
|
||||||
"""Get list of packages installed on disk"""
|
"""Get list of packages installed on disk"""
|
||||||
import addon_utils
|
import addon_utils
|
||||||
return [Package.from_module(mod) for mod in addon_utils.modules(refresh=refresh)]
|
return [Package.from_module(mod) for mod in addon_utils.modules(refresh=refresh)]
|
||||||
|
|
||||||
def get_packages_from_repo() -> list:
|
def get_packages_from_repo() -> list:
|
||||||
"""Get list of packages from cached repository lists (does not refresh them from server)"""
|
"""Get list of packages from cached repository lists (does not refresh them from server)"""
|
||||||
import pathlib
|
import pathlib
|
||||||
storage_path = pathlib.Path(bpy.utils.user_resource('CONFIG', 'packages', create=True)) / 'repo.json'
|
storage_path = pathlib.Path(bpy.utils.user_resource('CONFIG', 'packages', create=True)) / 'repo.json'
|
||||||
@@ -398,7 +403,7 @@ def get_packages_from_repo() -> list:
|
|||||||
pkg.repository = repo.name
|
pkg.repository = repo.name
|
||||||
return repo.packages
|
return repo.packages
|
||||||
|
|
||||||
class PACKAGE_OT_refresh_packages(bpy.types.Operator):
|
class PACKAGE_OT_refresh_packages(bpy.types.Operator):
|
||||||
bl_idname = "package.refresh_packages"
|
bl_idname = "package.refresh_packages"
|
||||||
bl_label = "Refresh Packages"
|
bl_label = "Refresh Packages"
|
||||||
bl_description = "Scan for packages on disk"
|
bl_description = "Scan for packages on disk"
|
||||||
@@ -414,7 +419,7 @@ class PACKAGE_OT_refresh_packages(bpy.types.Operator):
|
|||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
class PACKAGE_OT_refresh_repositories(SubprocMixin, bpy.types.Operator):
|
class PACKAGE_OT_refresh_repositories(SubprocMixin, bpy.types.Operator):
|
||||||
bl_idname = "package.refresh_repositories"
|
bl_idname = "package.refresh_repositories"
|
||||||
bl_label = "Refresh Repositories"
|
bl_label = "Refresh Repositories"
|
||||||
bl_description = 'Check repositories for new and updated packages'
|
bl_description = 'Check repositories for new and updated packages'
|
||||||
@@ -512,10 +517,10 @@ class PACKAGE_OT_refresh_repositories(SubprocMixin, bpy.types.Operator):
|
|||||||
self.log.error('Refresh process died without telling us! Exit code was 0 though')
|
self.log.error('Refresh process died without telling us! Exit code was 0 though')
|
||||||
self.report({'WARNING'}, 'Error refreshing package lists, but process finished OK. This is weird.')
|
self.report({'WARNING'}, 'Error refreshing package lists, but process finished OK. This is weird.')
|
||||||
|
|
||||||
#TODO:
|
#TODO:
|
||||||
# monkey patch refresh_repositories and add refresh_packages in the success callback
|
# monkey patch refresh_repositories and add refresh_packages in the success callback
|
||||||
# this way refresh_packages is always called after repositories have been refreshed
|
# this way refresh_packages is always called after repositories have been refreshed
|
||||||
class PACKAGE_OT_refresh(bpy.types.Operator):
|
class PACKAGE_OT_refresh(bpy.types.Operator):
|
||||||
bl_idname = "package.refresh"
|
bl_idname = "package.refresh"
|
||||||
bl_label = "Refresh"
|
bl_label = "Refresh"
|
||||||
bl_description = "Check for new and updated packages"
|
bl_description = "Check for new and updated packages"
|
||||||
@@ -525,7 +530,7 @@ class PACKAGE_OT_refresh(bpy.types.Operator):
|
|||||||
# getattr(bpy.ops, __package__).refresh_packages()
|
# getattr(bpy.ops, __package__).refresh_packages()
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
class RepositoryProperty(bpy.types.PropertyGroup):
|
class RepositoryProperty(bpy.types.PropertyGroup):
|
||||||
url = bpy.props.StringProperty(name="URL")
|
url = bpy.props.StringProperty(name="URL")
|
||||||
status = bpy.props.EnumProperty(name="Status", items=[
|
status = bpy.props.EnumProperty(name="Status", items=[
|
||||||
("OK", "Okay", "FILE_TICK"),
|
("OK", "Okay", "FILE_TICK"),
|
||||||
@@ -533,7 +538,7 @@ class RepositoryProperty(bpy.types.PropertyGroup):
|
|||||||
("NOCONNECT", "Could not connect", "QUESTION"),
|
("NOCONNECT", "Could not connect", "QUESTION"),
|
||||||
])
|
])
|
||||||
|
|
||||||
class PACKAGE_UL_repositories(bpy.types.UIList):
|
class PACKAGE_UL_repositories(bpy.types.UIList):
|
||||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||||
layout.alignment='LEFT'
|
layout.alignment='LEFT'
|
||||||
if len(item.name) == 0:
|
if len(item.name) == 0:
|
||||||
@@ -541,7 +546,7 @@ class PACKAGE_UL_repositories(bpy.types.UIList):
|
|||||||
else:
|
else:
|
||||||
layout.label(item.name)
|
layout.label(item.name)
|
||||||
|
|
||||||
class PACKAGE_OT_add_repository(bpy.types.Operator):
|
class PACKAGE_OT_add_repository(bpy.types.Operator):
|
||||||
bl_idname = "package.add_repository"
|
bl_idname = "package.add_repository"
|
||||||
bl_label = "Add Repository"
|
bl_label = "Add Repository"
|
||||||
|
|
||||||
@@ -567,7 +572,7 @@ class PACKAGE_OT_add_repository(bpy.types.Operator):
|
|||||||
context.area.tag_redraw()
|
context.area.tag_redraw()
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
class PACKAGE_OT_remove_repository(bpy.types.Operator):
|
class PACKAGE_OT_remove_repository(bpy.types.Operator):
|
||||||
bl_idname = "package.remove_repository"
|
bl_idname = "package.remove_repository"
|
||||||
bl_label = "Remove Repository"
|
bl_label = "Remove Repository"
|
||||||
|
|
||||||
@@ -576,7 +581,7 @@ class PACKAGE_OT_remove_repository(bpy.types.Operator):
|
|||||||
prefs.repositories.remove(prefs.active_repository)
|
prefs.repositories.remove(prefs.active_repository)
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
class USERPREF_PT_packages(bpy.types.Panel):
|
class USERPREF_PT_packages(bpy.types.Panel):
|
||||||
bl_label = "Package Management"
|
bl_label = "Package Management"
|
||||||
bl_space_type = 'USER_PREFERENCES'
|
bl_space_type = 'USER_PREFERENCES'
|
||||||
bl_region_type = 'WINDOW'
|
bl_region_type = 'WINDOW'
|
||||||
@@ -893,7 +898,7 @@ class USERPREF_PT_packages(bpy.types.Panel):
|
|||||||
draw_package(_packages[pkgname], row)
|
draw_package(_packages[pkgname], row)
|
||||||
|
|
||||||
|
|
||||||
class WM_OT_package_toggle_expand(bpy.types.Operator):
|
class WM_OT_package_toggle_expand(bpy.types.Operator):
|
||||||
bl_idname = "wm.package_toggle_expand"
|
bl_idname = "wm.package_toggle_expand"
|
||||||
bl_label = ""
|
bl_label = ""
|
||||||
bl_description = "Toggle display of extended information for given package (hold shift to collapse all other packages)"
|
bl_description = "Toggle display of extended information for given package (hold shift to collapse all other packages)"
|
||||||
@@ -916,7 +921,7 @@ class WM_OT_package_toggle_expand(bpy.types.Operator):
|
|||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
class PACKAGE_OT_toggle_enabled(bpy.types.Operator):
|
class PACKAGE_OT_toggle_enabled(bpy.types.Operator):
|
||||||
bl_idname = "package.toggle_enabled"
|
bl_idname = "package.toggle_enabled"
|
||||||
bl_label = ""
|
bl_label = ""
|
||||||
bl_description = "Enable given package if it's disabled, and vice versa if it's enabled"
|
bl_description = "Enable given package if it's disabled, and vice versa if it's enabled"
|
||||||
@@ -957,7 +962,7 @@ class PACKAGE_OT_toggle_enabled(bpy.types.Operator):
|
|||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
class PACKAGE_OT_disable(bpy.types.Operator):
|
class PACKAGE_OT_disable(bpy.types.Operator):
|
||||||
bl_idname = "package.disable"
|
bl_idname = "package.disable"
|
||||||
bl_label = ""
|
bl_label = ""
|
||||||
bl_description = "Disable given package"
|
bl_description = "Disable given package"
|
||||||
@@ -982,7 +987,7 @@ class PACKAGE_OT_disable(bpy.types.Operator):
|
|||||||
_packages[self.package_name].enabled = False
|
_packages[self.package_name].enabled = False
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
class PackageManagerPreferences(bpy.types.AddonPreferences):
|
class PackageManagerPreferences(bpy.types.AddonPreferences):
|
||||||
bl_idname = __package__
|
bl_idname = __package__
|
||||||
|
|
||||||
repositories = bpy.props.CollectionProperty(
|
repositories = bpy.props.CollectionProperty(
|
||||||
@@ -991,11 +996,11 @@ class PackageManagerPreferences(bpy.types.AddonPreferences):
|
|||||||
)
|
)
|
||||||
active_repository = bpy.props.IntProperty()
|
active_repository = bpy.props.IntProperty()
|
||||||
|
|
||||||
def validate_packagelist(pkglist: list) -> list:
|
def validate_packagelist(pkglist: list) -> list:
|
||||||
"""Ensures all packages have required fields; strips out bad packages and returns them in a list"""
|
"""Ensures all packages have required fields; strips out bad packages and returns them in a list"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def build_composite_packagelist(installed: list, available: list) -> OrderedDict:
|
def build_composite_packagelist(installed: list, available: list) -> OrderedDict:
|
||||||
"""Merge list of installed and available packages into one dict, keyed by package name"""
|
"""Merge list of installed and available packages into one dict, keyed by package name"""
|
||||||
|
|
||||||
log = logging.getLogger(__name__ + ".build_composite_packagelist")
|
log = logging.getLogger(__name__ + ".build_composite_packagelist")
|
||||||
@@ -1065,7 +1070,7 @@ def build_composite_packagelist(installed: list, available: list) -> OrderedDict
|
|||||||
|
|
||||||
return OrderedDict(sorted(masterlist.items()))
|
return OrderedDict(sorted(masterlist.items()))
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
bpy.utils.register_class(PACKAGE_OT_install)
|
bpy.utils.register_class(PACKAGE_OT_install)
|
||||||
bpy.utils.register_class(PACKAGE_OT_uninstall)
|
bpy.utils.register_class(PACKAGE_OT_uninstall)
|
||||||
bpy.utils.register_class(PACKAGE_OT_toggle_enabled)
|
bpy.utils.register_class(PACKAGE_OT_toggle_enabled)
|
||||||
@@ -1097,7 +1102,7 @@ def register():
|
|||||||
bpy.utils.register_class(PackageManagerPreferences)
|
bpy.utils.register_class(PackageManagerPreferences)
|
||||||
|
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
bpy.utils.unregister_class(PACKAGE_OT_install)
|
bpy.utils.unregister_class(PACKAGE_OT_install)
|
||||||
bpy.utils.unregister_class(PACKAGE_OT_uninstall)
|
bpy.utils.unregister_class(PACKAGE_OT_uninstall)
|
||||||
bpy.utils.unregister_class(PACKAGE_OT_toggle_enabled)
|
bpy.utils.unregister_class(PACKAGE_OT_toggle_enabled)
|
||||||
|
Reference in New Issue
Block a user