From 469f10e4a7d3cfdd6cc937344dc47b89608198fa Mon Sep 17 00:00:00 2001 From: Will Kahn-Greene Date: Wed, 23 May 2012 21:16:18 -0400 Subject: Add plugin writer's quickstart guide --- docs/source/pluginwriter/quickstart.rst | 189 ++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 docs/source/pluginwriter/quickstart.rst (limited to 'docs/source/pluginwriter/quickstart.rst') diff --git a/docs/source/pluginwriter/quickstart.rst b/docs/source/pluginwriter/quickstart.rst new file mode 100644 index 00000000..73531381 --- /dev/null +++ b/docs/source/pluginwriter/quickstart.rst @@ -0,0 +1,189 @@ +.. MediaGoblin Documentation + + Written in 2011, 2012 by MediaGoblin contributors + + To the extent possible under law, the author(s) have dedicated all + copyright and related and neighboring rights to this software to + the public domain worldwide. This software is distributed without + any warranty. + + You should have received a copy of the CC0 Public Domain + Dedication along with this software. If not, see + . + + +=========== +Quick Start +=========== + +This is a quick start. It's not comprehensive, but it walks through +writing a basic plugin called "sampleplugin" which logs "I've been +started!" when ``setup_plugin()`` has been called. + +.. todo: Rewrite this to be a useful plugin + + +Step 1: Files and directories +============================= + +GNU MediaGoblin plugins are Python projects at heart. As such, you should +use a standard Python project directory tree:: + + sampleplugin/ + |- README + |- LICENSE + |- setup.py + |- sampleplugin/ + |- __init__.py + + +The outer ``sampleplugin`` directory holds all the project files. + +The ``README`` should cover what your plugin does, how to install it, +how to configure it, and all the sorts of things a README should +cover. + +The ``LICENSE`` should have the license under which you're +distributing your plugin. + +The inner ``sampleplugin`` directory is the Python package that holds +your plugin's code. + +The ``__init__.py`` denotes that this is a Python package. It also +holds the plugin code. + + +Step 2: README +============== + +Here's a rough ``README``. Generally, you want more information +because this is the file that most people open when they want to learn +more about your project. + +:: + + README + ====== + + This is a sample plugin. It logs a line when ``setup__plugin()`` is + run. + + +Step 3: LICENSE +=============== + +GNU MediaGoblin plugins must be licensed under the AGPLv3 or later. So +the LICENSE file should be the AGPLv3 text which you can find at +``_ + + +Step 4: setup.py +================ + +This file is used for packaging and distributing your plugin. + +We'll use a basic one:: + + from setuptools import setup, find_packages + + setup( + name='sampleplugin', + version='1.0', + packages=find_packages(), + include_package_data=True, + install_requires=[], + license='AGPLv3', + ) + + +See ``_ +for more details. + + +Step 5: the code +================ + +The code for ``__init__.py`` looks like this: + +.. code-block:: python + :linenos: + :emphasize-lines: 8,19 + + import logging + from mediagoblin.tools.pluginapi import Plugin, get_config + + + _log = logging.getLogger(__name__) + + + class SamplePlugin(Plugin): + """ + This is a sample plugin class. It automatically registers itself + with MediaGoblin when this module is imported. + + The setup_plugin method prints configuration for this plugin if + there is any. + """ + def __init__(self): + pass + + def setup_plugin(self): + _log.info("I've been started!") + config = get_config('sampleplugin') + if config: + _log.info('%r' % config) + else: + _log.info('There is no configuration set.') + + +Line 8 defines a class called ``SamplePlugin`` that subclasses +``Plugin`` from ``mediagoblin.tools.pluginapi``. When the class is +defined, it gets registered with MediaGoblin and MediaGoblin will then +call ``setup_plugin`` on it. + +Line 19 defines ``setup_plugin``. This gets called when MediaGoblin +starts up after it's registered all the plugins. This is where you can +do any initialization for your plugin. + + +Step 6: Installation and configuration +====================================== + +To install the plugin for development, you need to make sure it's +available to the Python interpreter that's running MediaGoblin. + +There are a couple of ways to do this, but we're going to pick the +easy one. + +Use ``python`` from your MediaGoblin virtual environment and do:: + + python setup.py develop + +Any changes you make to your plugin will be available in your +MediaGoblin virtual environment. + +Then adjust your ``mediagoblin.ini`` file to load the plugin:: + + [plugins] + + [[sampleplugin]] + + +Step 7: That's it! +================== + +When you launch MediaGoblin, it'll load the plugin and you'll see +evidence of that in the log file. + +That's it for the quick start! + + +Where to go from here +===================== + +See the documentation on the plugin API for code samples and other +things you can use when building your plugin. + +See `Hitchhiker's Guide to Packaging +`_ for more information on +packaging your plugin. -- cgit v1.2.3 From 05e007c1dbe7b5b8a092f1a99ed361c4e6b71f26 Mon Sep 17 00:00:00 2001 From: Will Kahn-Greene Date: Tue, 17 Jul 2012 21:02:12 -0400 Subject: Rework plugin infrastructure to nix side-effects This reworks the plugin infrastructure so as to remove module-loading side-effects which were making things a pain in the ass to test. With the new system, there's no auto-registering meta class. Instead plugins do whatever they want and then specify a hooks dict that maps hook names to callables for the things they're tying into. The most common one (and the only one we've implemented so far) is "setup". This also simplifies the sampleplugin a little by moving the code to __init__.py. --- docs/source/pluginwriter/quickstart.rst | 47 +++++++++++++++------------------ 1 file changed, 22 insertions(+), 25 deletions(-) (limited to 'docs/source/pluginwriter/quickstart.rst') diff --git a/docs/source/pluginwriter/quickstart.rst b/docs/source/pluginwriter/quickstart.rst index 73531381..b5a63f79 100644 --- a/docs/source/pluginwriter/quickstart.rst +++ b/docs/source/pluginwriter/quickstart.rst @@ -50,7 +50,8 @@ The inner ``sampleplugin`` directory is the Python package that holds your plugin's code. The ``__init__.py`` denotes that this is a Python package. It also -holds the plugin code. +holds the plugin code and the ``hooks`` dict that specifies which +hooks the sampleplugin uses. Step 2: README @@ -107,43 +108,39 @@ The code for ``__init__.py`` looks like this: .. code-block:: python :linenos: - :emphasize-lines: 8,19 + :emphasize-lines: 12,23 import logging from mediagoblin.tools.pluginapi import Plugin, get_config + # This creates a logger that you can use to log information to + # the console or a log file. _log = logging.getLogger(__name__) - class SamplePlugin(Plugin): - """ - This is a sample plugin class. It automatically registers itself - with MediaGoblin when this module is imported. + # This is the function that gets called when the setup + # hook fires. + def setup_plugin(): + _log.info("I've been started!") + config = get_config('sampleplugin') + if config: + _log.info('%r' % config) + else: + _log.info('There is no configuration set.') - The setup_plugin method prints configuration for this plugin if - there is any. - """ - def __init__(self): - pass - def setup_plugin(self): - _log.info("I've been started!") - config = get_config('sampleplugin') - if config: - _log.info('%r' % config) - else: - _log.info('There is no configuration set.') + # This is a dict that specifies which hooks this plugin uses. + # This one only uses one hook: setup. + hooks = { + 'setup': setup_plugin + } -Line 8 defines a class called ``SamplePlugin`` that subclasses -``Plugin`` from ``mediagoblin.tools.pluginapi``. When the class is -defined, it gets registered with MediaGoblin and MediaGoblin will then -call ``setup_plugin`` on it. +Line 12 defines the ``setup_plugin`` function. -Line 19 defines ``setup_plugin``. This gets called when MediaGoblin -starts up after it's registered all the plugins. This is where you can -do any initialization for your plugin. +Line 23 defines ``hooks``. When MediaGoblin loads this file, it sees +``hooks`` and registers all the callables with their respective hooks. Step 6: Installation and configuration -- cgit v1.2.3 From d861ffc9ad5118f251fa669028bf774d98b0b451 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Wed, 29 May 2013 14:10:07 -0500 Subject: Link to the plugin api stuff and the database plugin sections from the quickstart. This commit sponsored by Nathan Stephenson. Thank you! --- docs/source/pluginwriter/quickstart.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'docs/source/pluginwriter/quickstart.rst') diff --git a/docs/source/pluginwriter/quickstart.rst b/docs/source/pluginwriter/quickstart.rst index b5a63f79..6d45ea36 100644 --- a/docs/source/pluginwriter/quickstart.rst +++ b/docs/source/pluginwriter/quickstart.rst @@ -178,8 +178,10 @@ That's it for the quick start! Where to go from here ===================== -See the documentation on the plugin API for code samples and other -things you can use when building your plugin. +See the documentation on the :ref:`plugin-api-chapter` for code +samples and other things you can use when building your plugin. If +your plugin needs its own database models, see +:ref:`plugin-database-chapter`. See `Hitchhiker's Guide to Packaging `_ for more information on -- cgit v1.2.3