diff --git a/docs/index.rst b/docs/index.rst index 2897bc63..0e6ba583 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -55,6 +55,8 @@ A french version of the documentation is available at :doc:`fr/index`. getting_started settings themes + pelican-themes + plugins internals faq contribute diff --git a/docs/plugins.rst b/docs/plugins.rst new file mode 100644 index 00000000..6763f5ef --- /dev/null +++ b/docs/plugins.rst @@ -0,0 +1,75 @@ +.. _plugins: + +Plugins +####### + +Since version 2.8, pelican manages plugins. Plugins are a way to add feature to +pelican without having to directly hack pelican code. + +Pelican is shipped with a set of core plugins, but you can easily implement +your own (and this page describes how) + +How to use plugins? +==================== + +To load plugins, you have to specify a them in your settings file. You have two +ways to do so: by specifying strings with the path to the callables: :: + + PLUGINS = ['pelican.plugins.gravatar',] + +Or by importing them and adding them to the list:: + + from pelican.plugins import gravatar + PLUGINS = [gravatar, ] + +If your plugins are not in an importable path, you can specify a `PLUGIN_PATH` +in the settings:: + + PLUGIN_PATH = "plugins" + PLUGINS = ["list", "of", "plugins"] + +How to create plugins? +====================== + +Plugins are based on the concept of signals. Pelican sends signals and plugins +subscribe to those signals. The list of signals are defined in a following +section. + +The only rule to follow for plugins is to define a `register` callable, in +which you map the signals to your plugin logic. Let's take a simple exemple:: + + from pelican import signals + + def test(sender): + print "%s initialized !!" % sender + + def register(): + signals.initialized.connect(test) + + +List of signals +=============== + +Here is the list of currently implemented signals: + +========================= ============================ ===================== +Signal Arguments Description +========================= ============================ ===================== +initialized pelican object +article_generate_context article_generator, metadata +========================= ============================ ===================== + +The list is currently small, don't hesitate to add signals and make a pull +request if you need them! + +List of plugins +=============== + +Not all the list are described here, but a few of them have been extracted from +pelican core and provided in pelican.plugins. They are described here: + +Tag cloud +--------- + +Translation +----------- diff --git a/docs/settings.rst b/docs/settings.rst index 9c596da3..9287facd 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -51,6 +51,7 @@ Setting name (default value) what does it do? `PDF_GENERATOR` (``False``) Set to True if you want to have PDF versions of your documents. You will need to install `rst2pdf`. +`PLUGINS` (``[]``) The list of plugins to load. See :ref:`plugins`. `RELATIVE_URL` (``True``) Defines if pelican should use relative urls or not. `SITEURL` base URL of your website. Note that this is @@ -208,14 +209,14 @@ Setting name what does it do ? `GITHUB_URL` Your github URL (if you have one), it will then use it to create a github ribbon. `GOOGLE_ANALYTICS` 'UA-XXXX-YYYY' to activate google analytics. +`LINKS` A list of tuples (Title, Url) for links to appear on + the header. `PIWIK_URL` URL to your Piwik server - without 'http://' at the beginning. `PIWIK_SSL_URL` If the SSL-URL differs from the normal Piwik-URL you have to include this setting too. (optional) `PIWIK_SITE_ID` ID for the monitored website. You can find the ID in the Piwik admin interface > settings > websites. -`LINKS` A list of tuples (Title, Url) for links to appear on - the header. `SOCIAL` A list of tuples (Title, Url) to appear in the "social" section. `TWITTER_USERNAME` Allows to add a button on the articles to tweet about diff --git a/pelican/__init__.py b/pelican/__init__.py index 515434cc..7121318e 100644 --- a/pelican/__init__.py +++ b/pelican/__init__.py @@ -2,7 +2,7 @@ import argparse import os import time -from blinker import signal +from pelican import signals from pelican.generators import (ArticlesGenerator, PagesGenerator, StaticGenerator, PdfGenerator) @@ -46,7 +46,7 @@ class Pelican(object): raise Exception("Impossible to find the theme %s" % theme) self.init_plugins() - signal('pelican_initialized').send(self) + signals.initialized.send(self) def init_plugins(self): self.plugins = self.settings['PLUGINS'] diff --git a/pelican/generators.py b/pelican/generators.py index eb74aff9..38fa9da7 100755 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -8,8 +8,6 @@ import os import math import random -from blinker import signal - from jinja2 import Environment, FileSystemLoader from jinja2.exceptions import TemplateNotFound @@ -17,6 +15,7 @@ from pelican.utils import copy, get_relative_path, process_translations, open from pelican.contents import Article, Page, is_valid_content from pelican.readers import read_file from pelican.log import * +from pelican import signals class Generator(object): @@ -100,7 +99,6 @@ class ArticlesGenerator(Generator): self.dates = {} self.tags = defaultdict(list) self.categories = defaultdict(list) - self.signal = {'pelican_article_generate_context' : signal('pelican_article_generate_context')} super(ArticlesGenerator, self).__init__(*args, **kwargs) self.drafts = [] @@ -214,7 +212,7 @@ class ArticlesGenerator(Generator): and self.settings['FALLBACK_ON_FS_DATE']: metadata['date'] = datetime.fromtimestamp(os.stat(f).st_ctime) - self.signal['pelican_article_generate_context'].send(self, metadata=metadata) + signals.article_generate_context.send(self, metadata=metadata) article = Article(content, metadata, settings=self.settings, filename=f) if not is_valid_content(article, f): @@ -318,7 +316,7 @@ class StaticGenerator(Generator): final_path=None): """Copy all the paths from source to destination""" for path in paths: - copy(path, source, os.path.join(output_path, destination), final_path, + copy(path, source, os.path.join(output_path, destination), final_path, overwrite=True) def generate_output(self, writer): diff --git a/pelican/plugins/global_license.py b/pelican/plugins/global_license.py index b6913831..463a93b3 100644 --- a/pelican/plugins/global_license.py +++ b/pelican/plugins/global_license.py @@ -1,4 +1,4 @@ -from blinker import signal +from pelican import signals """ License plugin for Pelican @@ -19,5 +19,5 @@ def add_license(generator, metadata): and 'LICENSE' in generator.settings.keys(): metadata['license'] = generator.settings['LICENSE'] - -signal('pelican_article_generate_context').connect(add_license) +def register(): + signals.article_generate_context.connect(add_license) diff --git a/pelican/plugins/gravatar.py b/pelican/plugins/gravatar.py index 2601ada0..200bb5a5 100644 --- a/pelican/plugins/gravatar.py +++ b/pelican/plugins/gravatar.py @@ -1,6 +1,6 @@ import hashlib -from blinker import signal +from pelican import signals """ Gravata plugin for Pelican ========================== @@ -37,4 +37,4 @@ def add_gravatar(generator, metadata): def register(): - signal('pelican_article_generate_context').connect(add_gravatar) + signals.article_generate_context.connect(add_gravatar) diff --git a/pelican/plugins/initialized.py b/pelican/plugins/initialized.py index 076ba06d..5e4cf174 100644 --- a/pelican/plugins/initialized.py +++ b/pelican/plugins/initialized.py @@ -1,8 +1,7 @@ -from blinker import signal - +from pelican import signals def test(sender): print "%s initialized !!" % sender def register(): - signal('pelican_initialized').connect(test) + signals.initialized.connect(test) diff --git a/pelican/settings.py b/pelican/settings.py index 3cc4157a..c1f15b2d 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -42,7 +42,7 @@ _DEFAULT_CONFIG = {'PATH': None, 'DEFAULT_METADATA': (), 'FILES_TO_COPY': (), 'DEFAULT_STATUS': 'published', - 'PLUGINS_PATH': None, + 'PLUGINS': [], } def read_settings(filename): diff --git a/pelican/signals.py b/pelican/signals.py new file mode 100644 index 00000000..f2bf4547 --- /dev/null +++ b/pelican/signals.py @@ -0,0 +1,4 @@ +from blinker import signal + +initialized = signal('pelican_initialized') +article_generate_context = signal('article_generate_context')