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.
|
# Django settings for authentic project.
|
||||||
import os
|
import os
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
|
||||||
|
from . import plugins
|
||||||
|
|
||||||
gettext_noop = lambda s: s
|
gettext_noop = lambda s: s
|
||||||
|
|
||||||
def to_boolean(name, default=True):
|
def to_boolean(name, default=True):
|
||||||
|
@ -149,6 +152,9 @@ INSTALLED_APPS = (
|
||||||
'south',
|
'south',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
INSTALLED_APPS = plugins.register_plugins_installed_apps('authentic2.plugin',
|
||||||
|
INSTALLED_APPS)
|
||||||
|
|
||||||
MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'
|
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
|
import authentic2.idp.views
|
||||||
|
|
||||||
from .admin import admin
|
from .admin import admin
|
||||||
from . import app_settings
|
from . import app_settings, plugins
|
||||||
|
|
||||||
admin.autodiscover()
|
admin.autodiscover()
|
||||||
handler500 = 'authentic2.views.server_error'
|
handler500 = 'authentic2.views.server_error'
|
||||||
|
@ -56,3 +56,5 @@ try:
|
||||||
)
|
)
|
||||||
except:
|
except:
|
||||||
pass
|
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