import bpy import logging from multiprocessing import Process, Pipe from . import blenderpack class SubprocessOperatorMixin: timer = None log = logging.getLogger("%s.SubprocessOperatorMixin" % __name__) # run once in invoke def setup(self): pass # run on receipt of data from subprocess def handle_response(self, resp): pass def __init__(self): self.pipe = Pipe() self.subprocess = None def execute(self, context): return self.invoke(context, None) def invoke(self, context, event): self.subprocess.start() # we have to explicitly close the end of the pipe we are NOT using, # otherwise no exception will be generated when the other process closes its end. self.pipe[1].close() wm = context.window_manager wm.modal_handler_add(self) self.timer = wm.event_timer_add(.01, context.window) self.setup() return {'RUNNING_MODAL'} def modal(self, context, event): self.log.debug("polling") try: if self.pipe[0].poll(): newdata = self.pipe[0].recv() else: newdata = None except EOFError: self.log.debug("done polling") return {'FINISHED'} if newdata is not None: self.handle_response(newdata) return {'PASS_THROUGH'} class PACKAGE_OT_fetch(SubprocessOperatorMixin, bpy.types.Operator): bl_idname = "package.fetch" bl_label = "Update package list(s)" last_response = None def __init__(self): super().__init__() settings = bpy.context.window_manager.package_manager_settings self.subprocess = Process(target=blenderpack.fetch, args=(settings.url, self.pipe)) def handle_response(self, resp): self.__class__.last_response = resp self.report({'INFO'}, "Request returned %s" % self.__class__.last_response) def execute(self, context): return {'FINISHED'} class PACKAGE_OT_add_repository(bpy.types.Operator): bl_idname = "package.add_repository" bl_label = "Add Repository" def execute(self, context): prefs = context.user_preferences.addons[__package__].preferences prefs.repositories.add() return {'FINISHED'} class PACKAGE_OT_remove_repository(bpy.types.Operator): bl_idname = "package.remove_repository" bl_label = "Remove Repository" def execute(self, context): prefs = context.user_preferences.addons[__package__].preferences prefs.repositories.remove(prefs.active_repository) return {'FINISHED'} def register(): bpy.utils.register_class(PACKAGE_OT_fetch) bpy.utils.register_class(PACKAGE_OT_add_repository) bpy.utils.register_class(PACKAGE_OT_remove_repository) def unregister(): bpy.utils.unregister_class(PACKAGE_OT_fetch) bpy.utils.unregister_class(PACKAGE_OT_remove_repository)