Asynchronous IPC: Initial implementation
This commit adds a mixin which sets up a modal operator which: * Starts a subprocess * Polls for messages from that subprocesses
This commit is contained in:
12
__init__.py
12
__init__.py
@@ -9,11 +9,18 @@ import bpy
|
||||
class PackageSettings(bpy.types.PropertyGroup):
|
||||
url = bpy.props.StringProperty(name="URL")
|
||||
|
||||
# class PackageManager:
|
||||
# # For some reason accessing 'settings' PointerProperty via wm.package_manager.settings gives a value error
|
||||
# # but accessing it when not stored in this class (wm.package_manager_settings) is fine?
|
||||
# # settings = bpy.props.PointerProperty(type=PackageSettings)
|
||||
# pipes = []
|
||||
|
||||
def register():
|
||||
from . import (pkg_ops, pkg_ui)
|
||||
|
||||
bpy.utils.register_class(PackageSettings)
|
||||
bpy.types.WindowManager.PackageManagerSettings = bpy.props.PointerProperty(type=PackageSettings)
|
||||
# bpy.types.WindowManager.package_manager = PackageManager()
|
||||
bpy.types.WindowManager.package_manager_settings = bpy.props.PointerProperty(type=PackageSettings)
|
||||
pkg_ops.register()
|
||||
pkg_ui.register()
|
||||
|
||||
@@ -22,5 +29,6 @@ def unregister():
|
||||
|
||||
pkg_ops.unregister()
|
||||
pkg_ui.unregister();
|
||||
del bpy.types.WindowManager.PackageManagerSettings
|
||||
bpy.utils.unregister_class(PackageSettings)
|
||||
del bpy.types.WindowManager.package_manager
|
||||
|
||||
|
@@ -21,10 +21,20 @@ SCHEMA_VERSION = 1
|
||||
class BadAddon(Exception):
|
||||
pass
|
||||
|
||||
def fetch(url):
|
||||
# TODO: do conditional request
|
||||
re = requests.get(url)
|
||||
print(re.json())
|
||||
def fetch(url, pipe):
|
||||
pipe[0].close()
|
||||
try:
|
||||
# TODO: do conditional request
|
||||
re = requests.get(url)
|
||||
# print(re.json())
|
||||
pipe[1].send(re.headers)
|
||||
finally:
|
||||
pipe[1].close()
|
||||
|
||||
|
||||
|
||||
# class Package():
|
||||
# def __init__(self):
|
||||
|
||||
|
||||
def parse_blinfo(source: str) -> dict:
|
||||
|
69
pkg_ops.py
69
pkg_ops.py
@@ -1,21 +1,72 @@
|
||||
import bpy
|
||||
from multiprocessing import Process
|
||||
import logging
|
||||
from multiprocessing import Process, Pipe
|
||||
from . import blenderpack
|
||||
|
||||
class PACKAGE_OT_fetch_lists(bpy.types.Operator):
|
||||
bl_idname = "package.fetch_lists"
|
||||
bl_label = "Update package list(s)"
|
||||
class SubprocessOperatorMixin:
|
||||
timer = None
|
||||
|
||||
# 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):
|
||||
print("polling")
|
||||
try:
|
||||
if self.pipe[0].poll():
|
||||
newdata = self.pipe[0].recv()
|
||||
else:
|
||||
newdata = None
|
||||
except EOFError:
|
||||
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)"
|
||||
|
||||
def __init__(self):
|
||||
SubprocessOperatorMixin.__init__(self)
|
||||
settings = bpy.context.window_manager.package_manager_settings
|
||||
self.subprocess = Process(target=blenderpack.fetch, args=(settings.url, self.pipe))
|
||||
|
||||
def handle_response(self, resp):
|
||||
print("your response:", resp)
|
||||
|
||||
def execute(self, context):
|
||||
settings = context.window_manager.PackageManagerSettings
|
||||
proc = Process(target=lambda: blenderpack.fetch(settings.url))
|
||||
proc.start()
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
def register():
|
||||
bpy.utils.register_class(PACKAGE_OT_fetch_lists)
|
||||
bpy.utils.register_class(PACKAGE_OT_fetch)
|
||||
|
||||
def unregister():
|
||||
bpy.utils.unregister_class(PACKAGE_OT_fetch_lists)
|
||||
bpy.utils.unregister_class(PACKAGE_OT_fetch)
|
||||
|
||||
|
@@ -16,8 +16,8 @@ class USERPREF_PT_packages(bpy.types.Panel):
|
||||
layout = self.layout
|
||||
|
||||
row = layout.row()
|
||||
row.prop(context.window_manager.PackageManagerSettings, "url")
|
||||
row.operator(pkg_ops.PACKAGE_OT_fetch_lists.bl_idname, text="Fetch")
|
||||
row.prop(context.window_manager.package_manager_settings, "url")
|
||||
row.operator(pkg_ops.PACKAGE_OT_fetch.bl_idname, text="Fetch")
|
||||
|
||||
def register():
|
||||
bpy.utils.register_class(USERPREF_PT_packages)
|
||||
|
Reference in New Issue
Block a user