summaryrefslogtreecommitdiffstats
path: root/docs/write_addons.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/write_addons.rst')
-rw-r--r--docs/write_addons.rst158
1 files changed, 158 insertions, 0 deletions
diff --git a/docs/write_addons.rst b/docs/write_addons.rst
new file mode 100644
index 000000000..9f4436cc5
--- /dev/null
+++ b/docs/write_addons.rst
@@ -0,0 +1,158 @@
+.. _write_addons:
+
+Addons
+======
+
+A Addon is a python file which is located at :file:`pyload/plugin/addon`.
+The :class:`AddonManager <pyload.manager.Addon.AddonManager>` will load it automatically on startup. Only one instance exists
+over the complete lifetime of pyload. Your addon can interact on various events called by the :class:`AddonManager <pyload.manager.Addon.AddonManager>`,
+do something complete autonomic and has full access to the :class:`Api <pyload.api.Api>` and every detail of pyLoad.
+The UpdateManager, CaptchaTrader, UnRar and many more are realised as addon.
+
+Addon header
+-----------
+
+Your addon needs to subclass :class:`Addon <pyload.plugin.Addon.Addon>` and will inherit all of its method, make sure to check its documentation!
+
+All addons should start with something like this: ::
+
+ from pyload.plugin.Addon import Addon
+
+ class YourAddon(Addon):
+ __name = "YourAddon"
+ __version = "0.1"
+ __description = "Does really cool stuff"
+ __config = [ ("activated" , "bool" , "Activated" , "True" ) ]
+ __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
+addon 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 Addon action takes places.
+
+The easiest way is to overwrite specific methods defined by the :class:`Addon <pyload.plugin.Addon.Addon>` base class.
+The name is indicating when the function gets called.
+See :class:`Addon <pyload.plugin.Addon.Addon>` page for a complete listing.
+
+You should be aware of the arguments the Addon is called with, whether its a :class:`PyFile <pyload.datatype.File.PyFile>`
+or :class:`PyPackage <pyload.datatype.Package.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 pyload.plugin.Addon import Addon
+
+ class YourAddon(Addon):
+ """
+ Your Addon code here.
+ """
+
+ def activate(self):
+ print "Yay, the core is ready let's do some work."
+
+ def downloadFinished(self, pyfile):
+ print "A Download just finished."
+
+Another and more flexible and powerful way is to use event listener.
+All addon methods exists as event and very useful additional events are dispatched by the core. For a little overview look
+at :class:`AddonManager <pyload.manager.Addon.AddonManager>`. 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 pyload.plugin.Addon import Addon
+
+ class YourAddon(Addon):
+ """
+ Your Addon code here.
+ """
+ event_map = {'downloadFinished': "doSomeWork",
+ 'allDownloadsFnished': "someMethod",
+ 'activate': "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:`AddonManager <pyload.manager.Addon.AddonManager>`. 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 addons. So all future interaction will be exclusive
+available as event and not accessible through overwriting addon 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 <pyload.api.Api>`, which can be used internal or called by clients via RPC.
+So probably clients want to be able to interact with your addon to request it's state or invoke some action.
+
+Sounds complicated but is very easy to do. Just use the ``Expose`` decorator: ::
+
+ from pyload.plugin.Addon import Addon, Expose
+
+ class YourAddon(Addon):
+ """
+ Your Addon code here.
+ """
+
+ @Expose
+ def invoke(self, arg):
+ print "Invoked with", arg
+
+Thats all, it's available via the :class:`Api <pyload.api.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("YourAddon", "invoke", "an argument"))
+
+Providing status information
+----------------------------
+Your addon can store information in a ``dict`` that can easily be retrievied via the :class:`Api <pyload.api.Api>`.
+
+Just store everything in ``self.info``. ::
+
+ from pyload.plugin.Addon import Addon
+
+ class YourAddon(Addon):
+ """
+ Your Addon code here.
+ """
+
+ def setup(self):
+ self.info = {'running': False}
+
+ def activate(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:`pyload/plugin/addon` and you will find plenty examples there.