From 4df2b77fdf42046fe19bd371be7c7255986b5980 Mon Sep 17 00:00:00 2001 From: RaNaN Date: Tue, 6 Mar 2012 13:36:39 +0100 Subject: renamed hooks to addons, new filemanager and database, many new api methods you will loose ALL your LINKS, webinterface will NOT work --- docs/plugins/addon_plugin.rst | 162 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 docs/plugins/addon_plugin.rst (limited to 'docs/plugins/addon_plugin.rst') diff --git a/docs/plugins/addon_plugin.rst b/docs/plugins/addon_plugin.rst new file mode 100644 index 000000000..57c7e4a96 --- /dev/null +++ b/docs/plugins/addon_plugin.rst @@ -0,0 +1,162 @@ +.. _write_addons: + +Addon - Add new functionality +============================= + +A Hook is a python file which is located at :file:`module/plugins/hooks`. +The :class:`HookManager ` will load it automatically on startup. Only one instance exists +over the complete lifetime of pyload. Your hook can interact on various events called by the :class:`HookManager `, +do something complete autonomic and has full access to the :class:`Api ` and every detail of pyLoad. +The UpdateManager, CaptchaTrader, UnRar and many more are realised as hooks. + +Hook header +----------- + +Your hook needs to subclass :class:`Hook ` and will inherit all of its method, make sure to check its documentation! + +All Hooks should start with something like this: :: + + from module.plugins.Hook import Hook + + class YourHook(Hook): + __name__ = "YourHook" + __version__ = "0.1" + __description__ = "Does really cool stuff" + __config__ = [ ("activated" , "bool" , "Activated" , "True" ) ] + __threaded__ = ["downloadFinished"] + __author_name__ = ("Me") + __author_mail__ = ("me@has-no-mail.com") + +All meta-data is defined in the header, you need at least one option at ``__config__`` so the user can toggle your +hook on and off. Dont't overwrite the ``init`` method if not neccesary, use ``setup`` instead. + +Using the Config +---------------- + +We are taking a closer look at the ``__config__`` parameter. +You can add more config values as desired by adding tuples of the following format to the config list: ``("name", "type", "description", "default value")``. +When everything went right you can access the config values with ``self.getConfig(name)`` and ``self.setConfig(name,value``. + + +Interacting on Events +--------------------- + +The next step is to think about where your Hook action takes places. + +The easiest way is to overwrite specific methods defined by the :class:`Hook ` base class. +The name is indicating when the function gets called. +See :class:`Hook ` page for a complete listing. + +You should be aware of the arguments the Hooks are called with, whether its a :class:`PyFile ` +or :class:`PyPackage ` you should read its related documentation to know how to access her great power and manipulate them. + +A basic excerpt would look like: :: + + from module.plugins.Hook import Hook + + class YourHook(Hook): + """ + Your Hook code here. + """ + + def coreReady(self): + print "Yay, the core is ready let's do some work." + + def downloadFinished(self, pyfile): + print "A Download just finished." + +Another important feature to mention can be seen at the ``__threaded__`` parameter. Function names listed will be executed +in a thread, in order to not block the main thread. This should be used for all kind of longer processing tasks. + +Another and more flexible and powerful way is to use event listener. +All hook methods exists as event and very useful additional events are dispatched by the core. For a little overview look +at :class:`HookManager `. Keep in mind that you can define own events and other people may listen on them. + +For your convenience it's possible to register listeners automatical via the ``event_map`` attribute. +It requires a `dict` that maps event names to function names or a `list` of function names. It's important that all names are strings :: + + from module.plugins.Hook import Hook + + class YourHook(Hook): + """ + Your Hook code here. + """ + event_map = {"downloadFinished" : "doSomeWork", + "allDownloadsFnished": "someMethod", + "coreReady": "initialize"} + + def initialize(self): + print "Initialized." + + def doSomeWork(self, pyfile): + print "This is equivalent to the above example." + + def someMethod(self): + print "The underlying event (allDownloadsFinished) for this method is not available through the base class" + +An advantage of the event listener is that you are able to register and remove the listeners at runtime. +Use `self.manager.addEvent("name", function)`, `self.manager.removeEvent("name", function)` and see doc for +:class:`HookManager `. Contrary to ``event_map``, ``function`` has to be a reference +and **not** a `string`. + +We introduced events because it scales better if there a a huge amount of events and hooks. So all future interaction will be exclusive +available as event and not accessible through overwriting hook methods. However you can safely do this, it will not be removed and is easier to implement. + + +Providing RPC services +---------------------- + +You may noticed that pyLoad has an :class:`Api `, which can be used internal or called by clients via RPC. +So probably clients want to be able to interact with your hook to request it's state or invoke some action. + +Sounds complicated but is very easy to do. Just use the ``Expose`` decorator: :: + + from module.plugins.Hook import Hook, Expose + + class YourHook(Hook): + """ + Your Hook code here. + """ + + @Expose + def invoke(self, arg): + print "Invoked with", arg + +Thats all, it's available via the :class:`Api ` now. If you want to use it read :ref:`access_api`. +Here is a basic example: :: + + #Assuming client is a ThriftClient or Api object + + print client.getServices() + print client.call(ServiceCall("YourHook", "invoke", "an argument")) + +Providing status information +---------------------------- +Your hook can store information in a ``dict`` that can easily be retrievied via the :class:`Api `. + +Just store everything in ``self.info``. :: + + from module.plugins.Hook import Hook + + class YourHook(Hook): + """ + Your Hook code here. + """ + + def setup(self): + self.info = {"running": False} + + def coreReady(self): + self.info["running"] = True + +Usable with: :: + + #Assuming client is a ThriftClient or Api object + + print client.getAllInfo() + +Example +------- + Sorry but you won't find an example here ;-) + + Look at :file:`module/plugins/hooks` and you will find plenty examples there. -- cgit v1.2.3 From 5a7f415a25d8e036a37851fcd5e9be81caae2804 Mon Sep 17 00:00:00 2001 From: X3n0m0rph59 Date: Sun, 22 Apr 2012 16:54:06 +0200 Subject: Fixed spelling in the documentation --- docs/plugins/addon_plugin.rst | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'docs/plugins/addon_plugin.rst') diff --git a/docs/plugins/addon_plugin.rst b/docs/plugins/addon_plugin.rst index 57c7e4a96..c2258f2aa 100644 --- a/docs/plugins/addon_plugin.rst +++ b/docs/plugins/addon_plugin.rst @@ -6,15 +6,15 @@ Addon - Add new functionality A Hook is a python file which is located at :file:`module/plugins/hooks`. The :class:`HookManager ` will load it automatically on startup. Only one instance exists over the complete lifetime of pyload. Your hook can interact on various events called by the :class:`HookManager `, -do something complete autonomic and has full access to the :class:`Api ` and every detail of pyLoad. -The UpdateManager, CaptchaTrader, UnRar and many more are realised as hooks. +do something completely autonomic and has full access to the :class:`Api ` and every detail of pyLoad. +The UpdateManager, CaptchaTrader, UnRar and many more are implemented as hooks. Hook header ----------- -Your hook needs to subclass :class:`Hook ` and will inherit all of its method, make sure to check its documentation! +Your hook needs to subclass :class:`Hook ` and will inherit all of its methods, so make sure to check it's documentation! -All Hooks should start with something like this: :: +All hooks should start with something like this: :: from module.plugins.Hook import Hook @@ -28,7 +28,7 @@ All Hooks should start with something like this: :: __author_mail__ = ("me@has-no-mail.com") All meta-data is defined in the header, you need at least one option at ``__config__`` so the user can toggle your -hook on and off. Dont't overwrite the ``init`` method if not neccesary, use ``setup`` instead. +hook on and off. Don't overwrite the ``init`` method if not necessary, use ``setup`` instead. Using the Config ---------------- @@ -41,16 +41,16 @@ When everything went right you can access the config values with ``self.getConfi Interacting on Events --------------------- -The next step is to think about where your Hook action takes places. +The next step is to think about where your Hook action takes place. The easiest way is to overwrite specific methods defined by the :class:`Hook ` base class. The name is indicating when the function gets called. See :class:`Hook ` page for a complete listing. -You should be aware of the arguments the Hooks are called with, whether its a :class:`PyFile ` -or :class:`PyPackage ` you should read its related documentation to know how to access her great power and manipulate them. +You should be aware of the arguments the hooks are called with, whether its a :class:`PyFile ` +or :class:`PyPackage ` you should read the relevant documentation to know how to access it's great power and manipulate them. -A basic excerpt would look like: :: +What a basic excerpt would look like: :: from module.plugins.Hook import Hook @@ -66,13 +66,13 @@ A basic excerpt would look like: :: print "A Download just finished." Another important feature to mention can be seen at the ``__threaded__`` parameter. Function names listed will be executed -in a thread, in order to not block the main thread. This should be used for all kind of longer processing tasks. +in a thread, in order to not block the main thread. This should be used for all kinds of long lived processing tasks. -Another and more flexible and powerful way is to use event listener. +Another and more flexible and powerful way is to use the event listener. All hook methods exists as event and very useful additional events are dispatched by the core. For a little overview look -at :class:`HookManager `. Keep in mind that you can define own events and other people may listen on them. +at :class:`HookManager `. Keep in mind that you can define your own events and other people may listen on them. -For your convenience it's possible to register listeners automatical via the ``event_map`` attribute. +For your convenience it's possible to register listeners automatically via the ``event_map`` attribute. It requires a `dict` that maps event names to function names or a `list` of function names. It's important that all names are strings :: from module.plugins.Hook import Hook @@ -99,14 +99,15 @@ Use `self.manager.addEvent("name", function)`, `self.manager.removeEvent("name", :class:`HookManager `. Contrary to ``event_map``, ``function`` has to be a reference and **not** a `string`. -We introduced events because it scales better if there a a huge amount of events and hooks. So all future interaction will be exclusive +We introduced events because it scales better if there is a huge amount of events and hooks. So all future interactions will be exclusively available as event and not accessible through overwriting hook methods. However you can safely do this, it will not be removed and is easier to implement. -Providing RPC services +Providing + RPC services ---------------------- -You may noticed that pyLoad has an :class:`Api `, which can be used internal or called by clients via RPC. +You may have noticed that pyLoad has an :class:`Api `, which can be used internal or called by clients via RPC. So probably clients want to be able to interact with your hook to request it's state or invoke some action. Sounds complicated but is very easy to do. Just use the ``Expose`` decorator: :: -- cgit v1.2.3