60 lines
2.0 KiB
Python
60 lines
2.0 KiB
Python
from abc import ABC, abstractmethod
|
|
|
|
class XtendRBase(ABC):
|
|
"""Abstract base class for all plugins.
|
|
|
|
Lifecycle: pre_load() -> run() -> stop() -> unload(). XtendRSystem calls
|
|
unload() exactly once, right before it drops its own references to the
|
|
plugin instance and removes its module from sys.modules. This is the
|
|
plugin's only chance to release anything it holds that XtendRSystem
|
|
doesn't know about and can't clean up on its own, for example:
|
|
|
|
- GObject/GTK signal handler ids from .connect() (disconnect them, or
|
|
the GObject side keeps a reference to the bound method, which keeps
|
|
the plugin instance -- and everything it references -- alive).
|
|
- Widgets the plugin inserted into the app's widget tree (remove them
|
|
from their parent; a parented widget is kept alive by GTK regardless
|
|
of what Python does with its own references).
|
|
- GLib.timeout_add / idle_add source ids (GLib.source_remove them).
|
|
- Any threads it started that aren't daemon threads, or open files/
|
|
sockets/subprocesses.
|
|
|
|
unload() has a default no-op implementation so existing plugins that
|
|
don't hold any such resources keep working unchanged; override it only
|
|
when there's something to release.
|
|
|
|
Example:
|
|
>>> class TestPlugin(XtendRBase):
|
|
... def run(self):
|
|
... print("Running TestPlugin")
|
|
... def stop(self):
|
|
... print("Stopping TestPlugin")
|
|
... def unload(self):
|
|
... print("Unloading TestPlugin")
|
|
|
|
>>> plugin = TestPlugin()
|
|
>>> plugin.run()
|
|
Running TestPlugin
|
|
>>> plugin.stop()
|
|
Stopping TestPlugin
|
|
>>> plugin.unload()
|
|
Unloading TestPlugin
|
|
"""
|
|
@abstractmethod
|
|
def run(self, *args, **kwargs):
|
|
pass
|
|
|
|
@abstractmethod
|
|
def stop(self):
|
|
pass
|
|
|
|
@abstractmethod
|
|
def pre_load(self, *args):
|
|
pass
|
|
|
|
def unload(self):
|
|
"""Release any resources the plugin holds. Called once by
|
|
XtendRSystem.detach(), after stop(). Optional to override;
|
|
default is a no-op."""
|
|
pass
|