add a plugin system
A sample plugin can be found in samples/
This commit is contained in:
parent
3c1ce8f8b3
commit
9cddce0d37
|
@ -0,0 +1,77 @@
|
|||
"""
|
||||
Use setuptools entrypoints to find plugins
|
||||
|
||||
Propose helper methods to load urls from plugins or modify INSTALLED_APPS
|
||||
"""
|
||||
import pkg_resources
|
||||
import logging
|
||||
|
||||
|
||||
from django.conf.urls import patterns, include, url
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
__ALL__ = ['get_plugins']
|
||||
|
||||
PLUGIN_CACHE = {}
|
||||
|
||||
class PluginError(Exception):
|
||||
pass
|
||||
|
||||
def get_plugins(group_name, use_cache=True, *args, **kwargs):
|
||||
'''Traverse all entry points for group_name and instantiate them using args
|
||||
and kwargs.
|
||||
'''
|
||||
global PLUGIN_CACHE
|
||||
if group_name in PLUGIN_CACHE and use_cache:
|
||||
return PLUGIN_CACHE[group_name]
|
||||
plugins = []
|
||||
for entrypoint in pkg_resources.iter_entry_points(group_name):
|
||||
try:
|
||||
plugin_callable = entrypoint.load()
|
||||
except Exception, e:
|
||||
logger.exception('unable to load entrypoint %s', entrypoint)
|
||||
raise PluginError('unable to load entrypoint %s' % entrypoint, e)
|
||||
plugins.append(plugin_callable(*args, **kwargs))
|
||||
PLUGIN_CACHE[group_name] = plugins
|
||||
return plugins
|
||||
|
||||
def register_plugins_urls(group_name, urlpatterns):
|
||||
'''Call get_before_urls and get_after_urls on all plugins providing them
|
||||
and add those urls to the given urlpatterns.
|
||||
|
||||
URLs returned by get_before_urls() are added to the head of urlpatterns
|
||||
and those returned by get_after_urls() are added to the tail of
|
||||
urlpatterns.
|
||||
'''
|
||||
plugins = get_plugins(group_name)
|
||||
before_urls = []
|
||||
after_urls = []
|
||||
for plugin in plugins:
|
||||
if hasattr(plugin, 'get_before_urls'):
|
||||
urls = plugin.get_before_urls()
|
||||
before_urls.append(url('^', include(urls)))
|
||||
if hasattr(plugin, 'get_after_urls'):
|
||||
urls = plugin.get_after_urls()
|
||||
after_urls.append(url('^', include(urls)))
|
||||
before_patterns = patterns('', *before_urls)
|
||||
after_patterns = patterns('', *after_urls)
|
||||
return before_patterns + urlpatterns + after_patterns
|
||||
|
||||
def register_plugins_installed_apps(group_name, installed_apps):
|
||||
'''Call get_apps() on all plugins of group_name and add the returned
|
||||
applications path to the installed_apps sequence.
|
||||
|
||||
Applications already present are ignored.
|
||||
'''
|
||||
installed_apps = list(installed_apps)
|
||||
for plugin in get_plugins(group_name):
|
||||
if hasattr(plugin, 'get_apps'):
|
||||
apps = plugin.get_apps()
|
||||
for app in apps:
|
||||
if app not in installed_apps:
|
||||
installed_apps.append(app)
|
||||
return installed_apps
|
||||
|
|
@ -1,8 +1,11 @@
|
|||
# Django settings for authentic project.
|
||||
import os
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
import json
|
||||
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
|
||||
from . import plugins
|
||||
|
||||
gettext_noop = lambda s: s
|
||||
|
||||
def to_boolean(name, default=True):
|
||||
|
@ -149,6 +152,9 @@ INSTALLED_APPS = (
|
|||
'south',
|
||||
)
|
||||
|
||||
INSTALLED_APPS = plugins.register_plugins_installed_apps('authentic2.plugin',
|
||||
INSTALLED_APPS)
|
||||
|
||||
MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'
|
||||
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ from authentic2.idp.decorators import prevent_access_to_transient_users
|
|||
import authentic2.idp.views
|
||||
|
||||
from .admin import admin
|
||||
from . import app_settings
|
||||
from . import app_settings, plugins
|
||||
|
||||
admin.autodiscover()
|
||||
handler500 = 'authentic2.views.server_error'
|
||||
|
@ -56,3 +56,5 @@ try:
|
|||
)
|
||||
except:
|
||||
pass
|
||||
|
||||
urlpatterns = plugins.register_plugins_urls('authentic2.plugin', urlpatterns)
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
class Plugin(object):
|
||||
def get_before_urls(self):
|
||||
from . import urls
|
||||
return urls.urlpatterns
|
||||
|
||||
def get_apps(self):
|
||||
return [__name__]
|
|
@ -0,0 +1,4 @@
|
|||
from django.db import models
|
||||
|
||||
class MyModel(models.Model):
|
||||
a = models.TextField()
|
|
@ -0,0 +1,4 @@
|
|||
from django.conf.urls import patterns, url
|
||||
|
||||
urlpatterns = patterns('a2_test_plugin.views',
|
||||
url('^test/', 'test'))
|
|
@ -0,0 +1,4 @@
|
|||
from django.http import HttpResponse
|
||||
|
||||
def test(request):
|
||||
return HttpResponse('coucou')
|
|
@ -0,0 +1,17 @@
|
|||
#!/usr/bin/python
|
||||
from setuptools import setup, find_packages
|
||||
import os
|
||||
|
||||
setup(name='authentic2-test-plugin',
|
||||
version='1.0',
|
||||
license='AGPLv3',
|
||||
description='Authentic2 Test Plugin',
|
||||
author="Entr'ouvert",
|
||||
author_email="info@entrouvert.com",
|
||||
packages=find_packages(os.path.dirname(__file__) or '.'),
|
||||
entry_points={
|
||||
'authentic2.plugin': [
|
||||
'test-plugin = a2_test_plugin:Plugin',
|
||||
],
|
||||
},
|
||||
)
|
Loading…
Reference in New Issue