Merge pull request #1143 from normanjaeckel/PluginAPI

Change API for plugins, esp. for names and versions of plugins. Also enh...
This commit is contained in:
Norman Jäckel 2013-12-05 07:47:59 -08:00
commit 399ab5a96c
12 changed files with 177 additions and 67 deletions

View File

@ -14,6 +14,7 @@ Files:
- Enabled update and delete view for uploader refering to his own files.
Other:
- Changed widget api. Used new metaclass.
- Changed api for plugins.
Version 1.5.1 (unreleased)

View File

@ -7,8 +7,14 @@
{% block content %}
<h1>{% trans 'Version' %}</h1>
<ul>
{% for version in versions %}
<li>{{ version.0 }} {% trans 'Version' %} {{ version.1 }}</li>
{% for module in modules %}
<li>
{{ module.verbose_name }}
{% if module.description %}
({{ module.description }})
{% endif %}
{% trans 'Version' %} {{ module.version }}
</li>
{% endfor %}
</ul>
{% endblock %}

View File

@ -5,8 +5,10 @@ from django.core.exceptions import PermissionDenied
from django.utils.importlib import import_module
from haystack.views import SearchView as _SearchView
from openslides import get_git_commit_id, get_version, RELEASE
from openslides import get_version as get_openslides_version
from openslides import get_git_commit_id, RELEASE
from openslides.config.api import config
from openslides.utils.plugins import get_plugin_description, get_plugin_verbose_name, get_plugin_version
from openslides.utils.signals import template_manipulation
from openslides.utils.views import TemplateView
@ -22,41 +24,19 @@ class VersionView(TemplateView):
Adds version strings to the context.
"""
context = super(VersionView, self).get_context_data(**kwargs)
# OpenSlides version. During development the git commit id is added.
openslides_version_string = get_version()
if not RELEASE:
openslides_version_string += ' Commit %s' % get_git_commit_id()
context['versions'] = [('OpenSlides', openslides_version_string)]
if RELEASE:
description = ''
else:
description = 'Commit %s' % get_git_commit_id()
context['modules'] = [{'verbose_name': 'OpenSlides',
'description': description,
'version': get_openslides_version()}]
# Versions of plugins.
for plugin in settings.INSTALLED_PLUGINS:
# Get plugin
try:
mod = import_module(plugin)
except ImportError:
continue
# Get version.
try:
plugin_version = mod.get_version()
except AttributeError:
try:
plugin_version = mod.VERSION
except AttributeError:
continue
# Get name.
try:
plugin_name = mod.get_name()
except AttributeError:
try:
plugin_name = mod.NAME
except AttributeError:
plugin_name = mod.__name__.split('.')[0]
context['versions'].append((plugin_name, plugin_version))
context['modules'].append({'verbose_name': get_plugin_verbose_name(plugin),
'description': get_plugin_description(plugin),
'version': get_plugin_version(plugin)})
return context

View File

@ -2,11 +2,22 @@
from django.conf import settings
from django.conf.urls import include, patterns, url
from django.utils.importlib import import_module
from openslides.utils.plugins import get_urlpatterns
handler500 = 'openslides.utils.views.server_error'
urlpatterns = patterns(
urlpatterns = []
js_info_dict = {'packages': []}
for plugin in settings.INSTALLED_PLUGINS:
plugin_urlpatterns = get_urlpatterns(plugin)
if plugin_urlpatterns:
urlpatterns += plugin_urlpatterns
js_info_dict['packages'].append(plugin)
urlpatterns += patterns(
'',
(r'^agenda/', include('openslides.agenda.urls')),
(r'^motion/', include('openslides.motion.urls')),
@ -18,19 +29,6 @@ urlpatterns = patterns(
(r'^i18n/', include('django.conf.urls.i18n')),
)
js_info_dict = {'packages': []}
for plugin in settings.INSTALLED_PLUGINS:
try:
mod = import_module(plugin + '.urls')
except ImportError:
continue
plugin_name = mod.__name__.split('.')[0]
urlpatterns += patterns('', (r'^%s/' % plugin_name, include('%s.urls'
% plugin)))
js_info_dict['packages'].append(plugin)
# TODO: move this patterns into core or the participant app
urlpatterns += patterns(
'',

View File

@ -0,0 +1,82 @@
# -*- coding: utf-8 -*-
from django.utils.importlib import import_module
plugins = {}
def get_plugin(plugin):
"""
Returns the imported module. The plugin argument must be a python dotted
module path.
"""
try:
plugin = plugins[plugin]
except KeyError:
plugins[plugin] = import_module(plugin)
plugin = get_plugin(plugin)
return plugin
def get_plugin_verbose_name(plugin):
"""
Returns the verbose name of a plugin. The plugin argument must be a python
dotted module path.
"""
plugin = get_plugin(plugin)
try:
verbose_name = plugin.get_verbose_name()
except AttributeError:
try:
verbose_name = plugin.__verbose_name__
except AttributeError:
verbose_name = plugin.__name__
return verbose_name
def get_plugin_description(plugin):
"""
Returns the short descrption of a plugin. The plugin argument must be a
python dotted module path.
"""
plugin = get_plugin(plugin)
try:
description = plugin.get_description()
except AttributeError:
try:
description = plugin.__description__
except AttributeError:
description = ''
return description
def get_plugin_version(plugin):
"""
Returns the version string of a plugin. The plugin argument must be a#
python dotted module path.
"""
plugin = get_plugin(plugin)
try:
version = plugin.get_version()
except AttributeError:
try:
version = plugin.__version__
except AttributeError:
version = 'unknown'
return version
def get_urlpatterns(plugin):
"""
Returns the urlpatterns object for a plugin. The plugin argument must be
a python dotted module path.
"""
plugin = get_plugin(plugin)
try:
urlpatterns = plugin.urlpatterns
except AttributeError:
try:
urlpatterns = plugin.urls.urlpatterns
except AttributeError:
urlpatterns = None
return urlpatterns

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from django.test.client import Client
from mock import MagicMock, patch
from mock import patch
from openslides import get_version
from openslides.agenda.models import Item
@ -23,24 +23,10 @@ class VersionViewTest(TestCase):
@patch('openslides.core.views.settings')
def test_with_missing_plugin(self, mock_settings):
"""
Tests that an not existing app does not appear on the version view.
Tests that a not existing app does not appear on the version view.
"""
mock_settings.INSTALLED_PLUGINS = ('unexisting_app_nvhbkdfgmnsd',)
response = self.client.get('/version/')
self.assertNotContains(response, 'unexisting_app_nvhbkdfgmnsd', status_code=200)
@patch('openslides.core.views.settings')
@patch('openslides.core.views.import_module')
def test_with_plugin_without_version(self, mock_import_module, mock_settings):
"""
Tests that an exisiting app does not appear in the version view if
there are no version data.
"""
mock_settings.INSTALLED_PLUGINS = ('existing_app_without_version',)
mock_module = MagicMock(spec=['some_useless_attribute_ghbnckj756j36'])
mock_import_module.configure_mock(return_value=mock_module)
response = self.client.get('/version/')
self.assertNotContains(response, 'unexisting_app_nvhbkdfgmnsd', status_code=200)
self.assertRaises(ImportError, self.client.get, '/version/')
class SearchViewTest(TestCase):

View File

View File

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
from django.test.client import Client
from django.test.utils import override_settings
from openslides.utils.test import TestCase
@override_settings(INSTALLED_PLUGINS=('tests.plugin_api.test_plugin_one',))
class TestPluginOne(TestCase):
urls = 'tests.plugin_api.urls' # Use reloaded urlpatterns for this TestCase
def setUp(self):
self.admin_client = Client()
self.admin_client.login(username='admin', password='admin')
def test_version_page(self):
response = self.admin_client.get('/version/')
self.assertContains(response, 'Test Plugin ta3Ohmaiquee2phaf9ei')
self.assertContains(response, '(Short description of test plugin Sah9aiQuae5hoocai7ai)')
self.assertContains(response, ' Version test_version_string_MoHonepahfofiree6Iej')
def test_url_patterns(self):
response = self.admin_client.get('/test_plugin_one_url_Eexea4nie1fexaax3oX7/')
self.assertRedirects(response, '/version/')
@override_settings(INSTALLED_PLUGINS=('tests.plugin_api.test_plugin_two',))
class TestPluginTwo(TestCase):
def test_version_page(self):
admin_client = Client()
admin_client.login(username='admin', password='admin')
response = admin_client.get('/version/')
self.assertContains(response, 'tests.plugin_api.test_plugin_two')
self.assertContains(response, ' Version unknown')

View File

@ -0,0 +1,13 @@
# -*- coding: utf-8 -*-
from django.conf.urls import patterns, url
from django.views.generic import RedirectView
__verbose_name__ = 'Test Plugin ta3Ohmaiquee2phaf9ei'
__version__ = 'test_version_string_MoHonepahfofiree6Iej'
__description__ = 'Short description of test plugin Sah9aiQuae5hoocai7ai'
urlpatterns = patterns(
'',
url(r'^test_plugin_one_url_Eexea4nie1fexaax3oX7/$',
RedirectView.as_view(pattern_name='core_version', permanent=False)))

7
tests/plugin_api/urls.py Normal file
View File

@ -0,0 +1,7 @@
# -*- coding: utf-8 -*-
from openslides import urls
reload(urls)
urlpatterns = urls.urlpatterns

View File

@ -1,3 +1,5 @@
# -*- coding: utf-8 -*-
from django.conf.urls import patterns, url
from openslides.urls import urlpatterns