Skip to content

Commit 078c77e

Browse files
committed
Don't use bpy too early, or it fails on non-Blender deployments
1 parent e08ccf1 commit 078c77e

File tree

1 file changed

+91
-92
lines changed

1 file changed

+91
-92
lines changed

src/compas_blender/__init__.py

Lines changed: 91 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
try:
2323
import bpy
2424
except ImportError:
25-
pass
25+
bpy = None
2626

2727
try:
2828
import compas_blender.data
@@ -455,105 +455,104 @@ def _install_thread_target():
455455
except Exception as e:
456456
install_queue.put(("RESULT", (False, str(e))))
457457

458+
if bpy is not None:
459+
class COMPAS_OT_install_dependencies(bpy.types.Operator):
460+
bl_idname = "compas.install_dependencies"
461+
bl_label = "Install Dependencies"
462+
bl_description = "Install COMPAS and required dependencies (scipy, etc.)"
463+
464+
_timer = None
465+
_thread = None
466+
467+
def modal(self, context, event):
468+
if event.type == 'TIMER':
469+
while not install_queue.empty():
470+
try:
471+
msg_type, data = install_queue.get_nowait()
472+
except queue.Empty:
473+
break
458474

459-
class COMPAS_OT_install_dependencies(bpy.types.Operator):
460-
bl_idname = "compas.install_dependencies"
461-
bl_label = "Install Dependencies"
462-
bl_description = "Install COMPAS and required dependencies (scipy, etc.)"
463-
464-
_timer = None
465-
_thread = None
466-
467-
def modal(self, context, event):
468-
if event.type == 'TIMER':
469-
while not install_queue.empty():
470-
try:
471-
msg_type, data = install_queue.get_nowait()
472-
except queue.Empty:
473-
break
474-
475-
if msg_type == "LOG":
476-
_log_to_text_block(data)
477-
context.workspace.status_text_set(data)
478-
elif msg_type == "RESULT":
479-
success, msg = data
480-
481-
# Clear status text
482-
context.workspace.status_text_set(None)
483-
484-
if success:
485-
self.report({'INFO'}, "COMPAS dependencies installed. Please restart Blender.")
486-
# Invalidate import caches so find_spec works immediately
487-
importlib.invalidate_caches()
488-
else:
489-
self.report({'ERROR'}, msg)
490-
self.report({'WARNING'}, "Check the 'COMPAS_INSTALL_LOG' in the Text Editor for details.")
491-
492-
context.window_manager.event_timer_remove(self._timer)
493-
494-
# Force redraw of the preferences area if possible
495-
if context.area:
496-
context.area.tag_redraw()
475+
if msg_type == "LOG":
476+
_log_to_text_block(data)
477+
context.workspace.status_text_set(data)
478+
elif msg_type == "RESULT":
479+
success, msg = data
497480

498-
return {'FINISHED'}
499-
500-
return {'PASS_THROUGH'}
501-
502-
def execute(self, context):
503-
self.report({'INFO'}, "Installation started. Check COMPAS_INSTALL_LOG for progress...")
504-
505-
# Start thread
506-
self._thread = threading.Thread(target=_install_thread_target)
507-
self._thread.start()
508-
509-
self._timer = context.window_manager.event_timer_add(0.1, window=context.window)
510-
context.window_manager.modal_handler_add(self)
511-
return {'RUNNING_MODAL'}
481+
# Clear status text
482+
context.workspace.status_text_set(None)
483+
484+
if success:
485+
self.report({'INFO'}, "COMPAS dependencies installed. Please restart Blender.")
486+
# Invalidate import caches so find_spec works immediately
487+
importlib.invalidate_caches()
488+
else:
489+
self.report({'ERROR'}, msg)
490+
self.report({'WARNING'}, "Check the 'COMPAS_INSTALL_LOG' in the Text Editor for details.")
491+
492+
context.window_manager.event_timer_remove(self._timer)
493+
494+
# Force redraw of the preferences area if possible
495+
if context.area:
496+
context.area.tag_redraw()
497+
498+
return {'FINISHED'}
499+
500+
return {'PASS_THROUGH'}
512501

502+
def execute(self, context):
503+
self.report({'INFO'}, "Installation started. Check COMPAS_INSTALL_LOG for progress...")
504+
505+
# Start thread
506+
self._thread = threading.Thread(target=_install_thread_target)
507+
self._thread.start()
508+
509+
self._timer = context.window_manager.event_timer_add(0.1, window=context.window)
510+
context.window_manager.modal_handler_add(self)
511+
return {'RUNNING_MODAL'}
513512

514-
class COMPAS_PT_preferences(bpy.types.AddonPreferences):
515-
bl_idname = __package__
513+
class COMPAS_PT_preferences(bpy.types.AddonPreferences):
514+
bl_idname = __package__
516515

517-
def draw(self, context):
518-
layout = self.layout
516+
def draw(self, context):
517+
layout = self.layout
519518

520-
compas_spec = importlib.util.find_spec("compas")
519+
compas_spec = importlib.util.find_spec("compas")
521520

522-
if compas_spec:
523-
if compas:
524-
layout.label(text="COMPAS {} is installed.".format(compas.__version__), icon='CHECKMARK')
521+
if compas_spec:
522+
if compas:
523+
layout.label(text="COMPAS {} is installed.".format(compas.__version__), icon='CHECKMARK')
524+
else:
525+
layout.label(text="COMPAS is installed (Restart Blender to load).", icon='CHECKMARK')
526+
layout.operator("compas.install_dependencies", text="Reinstall / Update Dependencies")
525527
else:
526-
layout.label(text="COMPAS is installed (Restart Blender to load).", icon='CHECKMARK')
527-
layout.operator("compas.install_dependencies", text="Reinstall / Update Dependencies")
528-
else:
529-
layout.label(text="COMPAS is NOT installed.", icon='ERROR')
530-
layout.operator("compas.install_dependencies", text="Install Dependencies")
531-
532-
if importlib.util.find_spec("scipy"):
533-
layout.label(text="Dependencies are installed.", icon='CHECKMARK')
534-
else:
535-
layout.label(text="Dependencies are NOT installed.", icon='ERROR')
536-
528+
layout.label(text="COMPAS is NOT installed.", icon='ERROR')
529+
layout.operator("compas.install_dependencies", text="Install Dependencies")
537530

538-
def register():
539-
if "bpy" in sys.modules:
540-
print("COMPAS: Registering classes...")
541-
try:
542-
bpy.utils.register_class(COMPAS_OT_install_dependencies)
543-
bpy.utils.register_class(COMPAS_PT_preferences)
544-
print("COMPAS: Classes registered.")
545-
except Exception as e:
546-
print("COMPAS: Failed to register classes: {}".format(e))
547-
import traceback
548-
traceback.print_exc()
549-
550-
# Auto-install is disabled to prevent UI blocking/crashing.
551-
# User should use the button in Preferences.
552-
if compas is None or importlib.util.find_spec("scipy") is None:
553-
print("COMPAS: Dependencies missing. Please use the 'Install Dependencies' button in the COMPAS preferences.")
531+
if importlib.util.find_spec("scipy"):
532+
layout.label(text="Dependencies are installed.", icon='CHECKMARK')
533+
else:
534+
layout.label(text="Dependencies are NOT installed.", icon='ERROR')
535+
536+
537+
def register():
538+
if "bpy" in sys.modules:
539+
print("COMPAS: Registering classes...")
540+
try:
541+
bpy.utils.register_class(COMPAS_OT_install_dependencies)
542+
bpy.utils.register_class(COMPAS_PT_preferences)
543+
print("COMPAS: Classes registered.")
544+
except Exception as e:
545+
print("COMPAS: Failed to register classes: {}".format(e))
546+
import traceback
547+
traceback.print_exc()
548+
549+
# Auto-install is disabled to prevent UI blocking/crashing.
550+
# User should use the button in Preferences.
551+
if compas is None or importlib.util.find_spec("scipy") is None:
552+
print("COMPAS: Dependencies missing. Please use the 'Install Dependencies' button in the COMPAS preferences.")
554553

555554

556-
def unregister():
557-
if "bpy" in sys.modules:
558-
bpy.utils.unregister_class(COMPAS_OT_install_dependencies)
559-
bpy.utils.unregister_class(COMPAS_PT_preferences)
555+
def unregister():
556+
if "bpy" in sys.modules:
557+
bpy.utils.unregister_class(COMPAS_OT_install_dependencies)
558+
bpy.utils.unregister_class(COMPAS_PT_preferences)

0 commit comments

Comments
 (0)