docs: Fix bad link in api.rst. Fixes 1019
[mediagoblin.git] / docs / source / pluginwriter / api.rst
index 2a7f3c2dcbadccddd13a4dc92a58c9e081f1d578..a8763f9d6193a0a45e47114f68a65a0d11cd5aed 100644 (file)
@@ -42,7 +42,7 @@ exist yet: what to do then?
 The plan at present is that we are adding hooks as people need them,
 with community discussion.  If you find that you need a hook and
 MediaGoblin at present doesn't provide it at present, please
-`http://mediagoblin.org/pages/join.html <talk to us>`_!  We'll
+`talk to us <http://mediagoblin.org/pages/join.html`_!  We'll
 evaluate what to do from there.
 
 
@@ -69,6 +69,32 @@ example might look like::
 This means that when people enable your plugin in their config you'll
 be able to provide defaults as well as type validation.
 
+You can access this via the app_config variables in mg_globals, or you
+can use a shortcut to get your plugin's config section::
+
+  >>> from mediagoblin.tools import pluginapi
+  # Replace with the path to your plugin.
+  # (If an external package,  it won't be part of mediagoblin.plugins)
+  >>> floobie_config = pluginapi.get_config('mediagoblin.plugins.floobifier')
+  >>> floobie_dir = floobie_config['floobie_dir']
+  # This is the same as the above
+  >>> from mediagoblin import mg_globals
+  >>> config = mg_globals.global_config['plugins']['mediagoblin.plugins.floobifier']
+  >>> floobie_dir = floobie_config['floobie_dir']
+  
+A tip: you have access to the `%(here)s` variable in your config,
+which is the directory that the user's mediagoblin config is running
+out of.  So for example, your plugin may need a "floobie" directory to
+store floobs in.  You could give them a reasonable default that makes
+use of the default `user_dev` location, but allow users to override
+it, like so::
+
+  [plugin_spec]
+  floobie_dir = string(default="%(here)s/user_dev/floobs/")
+
+Note, this is relative to the user's mediagoblin config directory,
+*not* your plugin directory!
+
 
 Context Hooks
 -------------
@@ -202,7 +228,7 @@ This section aims to explain some tips in regards to adding hooks to
 the MediaGoblin repository.
 
 WTForms hooks
-=============
++++++++++++++
 
 We haven't totally settled on a way to tranform wtforms form objects,
 but here's one way.  In your view::
@@ -226,3 +252,71 @@ Then to hook into this form, do something in your plugin like::
 
   hooks = {
       'some_form_transform': transform_some_form}
+
+
+Interfaces
+++++++++++
+
+If you want to add a pseudo-interface, it's not difficult to do so.
+Just write the interface like so::
+
+  class FrobInterface(object):
+      """
+      Interface for Frobbing.
+
+      Classes implementing this interface should provide defrob and frob.
+      They may also implement double_frob, but it is not required; if
+      not provided, we will use a general technique.
+      """
+
+      def defrob(self, frobbed_obj):
+          """
+          Take a frobbed_obj and defrob it.  Returns the defrobbed object.
+          """
+          raise NotImplementedError()
+      
+      def frob(self, normal_obj):
+          """
+          Take a normal object and frob it.  Returns the frobbed object.
+          """
+          raise NotImplementedError()
+
+      def double_frob(self, normal_obj):
+          """
+          Frob this object and return it multiplied by two.
+          """
+          return self.frob(normal_obj) * 2
+
+
+  def some_frob_using_method():
+      # something something something
+      frobber = hook_handle(FrobInterface)
+      frobber.frob(blah)
+
+      # alternately you could have a default
+      frobber = hook_handle(FrobInterface) or DefaultFrobber
+      frobber.defrob(foo)
+
+
+It's fine to use your interface as the key instead of a string if you
+like.  (Usually this is messy, but since interfaces are public and
+since you need to import them into your plugin anyway, interfaces
+might as well be keys.)
+
+Then a plugin providing your interface can be like::
+
+  from mediagoblin.foo.frobfrogs import FrobInterface
+  from frogfrobber import utils
+
+  class FrogFrobber(FrobInterface):
+      """
+      Takes a frogputer science approach to frobbing.
+      """
+      def defrob(self, frobbed_obj):
+          return utils.frog_defrob(frobbed_obj)
+
+      def frob(self, normal_obj):
+          return utils.frog_frob(normal_obj)
+
+   hooks = {
+       FrobInterface: lambda: return FrogFrobber}