diff --git a/CHANGELOG b/CHANGELOG index ab35bb3c2..516f101ff 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -15,6 +15,7 @@ Files: Other: - Changed widget api. Used new metaclass. - Changed api for plugins. +- Renamed config api classes. Version 1.5.1 (unreleased) diff --git a/openslides/agenda/signals.py b/openslides/agenda/signals.py index 353a4649e..2c7f093c1 100644 --- a/openslides/agenda/signals.py +++ b/openslides/agenda/signals.py @@ -11,7 +11,7 @@ from django.template.loader import render_to_string from django.utils.translation import ugettext as _ from django.utils.translation import ugettext_lazy, ugettext_noop -from openslides.config.api import config, ConfigPage, ConfigVariable +from openslides.config.api import config, ConfigCollection, ConfigVariable from openslides.config.signals import config_signal from openslides.projector.api import get_active_slide, get_active_object from openslides.projector.projector import Overlay @@ -29,8 +29,8 @@ def validate_start_time(value): # TODO: Reinsert the datepicker scripts in the template -@receiver(config_signal, dispatch_uid='setup_agenda_config_page') -def setup_agenda_config_page(sender, **kwargs): +@receiver(config_signal, dispatch_uid='setup_agenda_config') +def setup_agenda_config(sender, **kwargs): """ Agenda config variables. """ @@ -66,15 +66,15 @@ def setup_agenda_config_page(sender, **kwargs): 'javascript/jquery-ui-sliderAccess.min.js', 'javascript/agenda-config-datepicker.js'] - return ConfigPage(title=ugettext_noop('Agenda'), - url='agenda', - required_permission='config.can_manage', - weight=20, - variables=(agenda_start_event_date_time, - agenda_show_last_speakers, - agenda_couple_countdown_and_speakers), - extra_context={'extra_stylefiles': extra_stylefiles, - 'extra_javascript': extra_javascript}) + return ConfigCollection(title=ugettext_noop('Agenda'), + url='agenda', + required_permission='config.can_manage', + weight=20, + variables=(agenda_start_event_date_time, + agenda_show_last_speakers, + agenda_couple_countdown_and_speakers), + extra_context={'extra_stylefiles': extra_stylefiles, + 'extra_javascript': extra_javascript}) @receiver(projector_overlays, dispatch_uid="agenda_list_of_speakers") diff --git a/openslides/assignment/signals.py b/openslides/assignment/signals.py index 64406d8bd..942bbe74e 100644 --- a/openslides/assignment/signals.py +++ b/openslides/assignment/signals.py @@ -5,12 +5,12 @@ from django.dispatch import receiver from django.utils.translation import ugettext as _ from django.utils.translation import ugettext_lazy, ugettext_noop -from openslides.config.api import ConfigPage, ConfigVariable +from openslides.config.api import ConfigCollection, ConfigVariable from openslides.config.signals import config_signal -@receiver(config_signal, dispatch_uid='setup_assignment_config_page') -def setup_assignment_config_page(sender, **kwargs): +@receiver(config_signal, dispatch_uid='setup_assignment_config') +def setup_assignment_config(sender, **kwargs): """ Assignment config variables. """ @@ -66,13 +66,13 @@ def setup_assignment_config_page(sender, **kwargs): ('votes', ugettext_lazy('Always one option per candidate')), ('yesnoabstain', ugettext_lazy('Always Yes-No-Abstain per candidate'))))) - return ConfigPage(title=ugettext_noop('Elections'), - url='assignment', - required_permission='config.can_manage', - weight=40, - variables=(assignment_publish_winner_results_only, - assignment_pdf_ballot_papers_selection, - assignment_pdf_ballot_papers_number, - assignment_pdf_title, - assignment_pdf_preamble, - assignment_poll_vote_values)) + return ConfigCollection(title=ugettext_noop('Elections'), + url='assignment', + required_permission='config.can_manage', + weight=40, + variables=(assignment_publish_winner_results_only, + assignment_pdf_ballot_papers_selection, + assignment_pdf_ballot_papers_number, + assignment_pdf_title, + assignment_pdf_preamble, + assignment_poll_vote_values)) diff --git a/openslides/config/api.py b/openslides/config/api.py index 305e51023..43bffe940 100644 --- a/openslides/config/api.py +++ b/openslides/config/api.py @@ -35,8 +35,8 @@ class ConfigHandler(object): pass # Call on_change callback - for receiver, config_page in config_signal.send(sender='set_value'): - for config_variable in config_page.variables: + for receiver, config_collection in config_signal.send(sender='set_value'): + for config_variable in config_collection.variables: if config_variable.name == key and config_variable.on_change: config_variable.on_change() break @@ -45,8 +45,8 @@ class ConfigHandler(object): """ Returns the default value for 'key'. """ - for receiver, config_page in config_signal.send(sender='get_default'): - for config_variable in config_page.variables: + for receiver, config_collection in config_signal.send(sender='get_default'): + for config_variable in config_collection.variables: if config_variable.name == key: return config_variable.default_value raise ConfigNotFound('The config variable %s was not found.' % key) @@ -57,8 +57,8 @@ class ConfigHandler(object): signal to get the default into the cache. """ self._cache = {} - for receiver, config_page in config_signal.send(sender='setup_cache'): - for config_variable in config_page.variables: + for receiver, config_collection in config_signal.send(sender='setup_cache'): + for config_variable in config_collection.variables: if config_variable.name in self._cache: raise ConfigError('Too many values for config variable %s found.' % config_variable.name) self._cache[config_variable.name] = config_variable.default_value @@ -81,15 +81,17 @@ use x = config[...], to set it use config[...] = x. """ -class ConfigBasePage(object): +class ConfigBaseCollection(object): """ - An abstract base class for simple and grouped config pages. The - attributes title and url are required. The attribute weight is used - for the order of the links in the submenu of the views. The attribute - extra_context can be used to insert extra css and js files into the - template. + An abstract base class for simple and grouped config collections. The + attributes title and url are required for collections that should be + shown as a view. The attribute required_permission is used to set which + users can control the view showing the colletion. The attribute weight + is used for the order of the links in the submenu of the views. The + attribute extra_context can be used to insert extra css and js files + into the template. """ - def __init__(self, title, url, required_permission=None, weight=0, extra_context={}): + def __init__(self, title=None, url=None, required_permission=None, weight=0, extra_context={}): self.title = title self.url = url self.required_permission = required_permission @@ -98,25 +100,29 @@ class ConfigBasePage(object): def is_shown(self): """ - Returns True if at least one variable of the page has a form field. + Returns True if at least one variable of the collection has a form field. """ for variable in self.variables: if variable.form_field is not None: - return True + is_shown = True + break else: - return False + is_shown = False + if is_shown and (self.title is None or self.url is None): + raise ConfigError('The config collection %s must have a title and an url attribute.' % self) + return is_shown -class ConfigGroupedPage(ConfigBasePage): +class ConfigGroupedCollection(ConfigBaseCollection): """ - A simple object class for a grouped config page. Developers have to + A simple object class for a grouped config collection. Developers have to set the groups attribute (tuple). The config variables are available - via the variables attribute. The page is shown as view in the config - tab, if there is at least one variable with a form field. + via the variables attribute. The collection is shown as a view via the config + main menu entry if there is at least one variable with a form field. """ def __init__(self, groups, **kwargs): self.groups = groups - super(ConfigGroupedPage, self).__init__(**kwargs) + super(ConfigGroupedCollection, self).__init__(**kwargs) @property def variables(self): @@ -125,15 +131,16 @@ class ConfigGroupedPage(ConfigBasePage): yield variable -class ConfigPage(ConfigBasePage): +class ConfigCollection(ConfigBaseCollection): """ - A simple object class for a ungrouped config page. Developers have - to set the variables (tuple) directly. The page is shown as view in - the config tab, if there is at least one variable with a form field. + A simple object class for a ungrouped config collection. Developers have + to set the variables (tuple) directly. The collection is shown as a view via + the config main menu entry if there is at least one variable with a + form field. """ def __init__(self, variables, **kwargs): self.variables = variables - super(ConfigPage, self).__init__(**kwargs) + super(ConfigCollection, self).__init__(**kwargs) class ConfigGroup(object): @@ -153,7 +160,7 @@ class ConfigVariable(object): """ A simple object class to wrap new config variables. The keyword arguments 'name' and 'default_value' are required. The keyword - argument 'form_field' has to be set, if the variable should appear + argument 'form_field' has to be set if the variable should appear on the ConfigView. The argument 'on_change' can get a callback which is called every time, the variable is changed. """ diff --git a/openslides/config/templates/config/config_form.html b/openslides/config/templates/config/config_form.html index b3ff44442..89b82542b 100644 --- a/openslides/config/templates/config/config_form.html +++ b/openslides/config/templates/config/config_form.html @@ -8,12 +8,14 @@ {% block content %}
{% include 'formbuttons_save.html' %} - {% trans 'Cancel' %} + {% trans 'Cancel' %}
* {% trans 'required' %} diff --git a/openslides/config/urls.py b/openslides/config/urls.py index 09a01c8b5..2821df267 100644 --- a/openslides/config/urls.py +++ b/openslides/config/urls.py @@ -11,11 +11,11 @@ urlpatterns = patterns( '', url(r'^$', RedirectView.as_view(url_name='config_general'), - name='config_first_config_page') + name='config_first_config_collection_view') ) -for receiver, config_page in config_signal.send(sender='config_urls'): - if config_page.is_shown(): - urlpatterns += patterns('', url(r'^%s/$' % config_page.url, - ConfigView.as_view(config_page=config_page), - name='config_%s' % config_page.url)) +for receiver, config_collection in config_signal.send(sender='config_urls'): + if config_collection.is_shown(): + urlpatterns += patterns('', url(r'^%s/$' % config_collection.url, + ConfigView.as_view(config_collection=config_collection), + name='config_%s' % config_collection.url)) diff --git a/openslides/config/views.py b/openslides/config/views.py index b0674ff63..49e7e2d1e 100644 --- a/openslides/config/views.py +++ b/openslides/config/views.py @@ -14,34 +14,34 @@ from .signals import config_signal class ConfigView(FormView): """ - The view for a config page. + The view for a config collection. """ template_name = 'config/config_form.html' - config_page = None + config_collection = None form_class = forms.Form def has_permission(self, *args, **kwargs): """ - Ensures that only users with tab's permission can see this view. + Ensures that only users with permission can see this view. """ - self.permission_required = self.config_page.required_permission + self.permission_required = self.config_collection.required_permission return super(ConfigView, self).has_permission(*args, **kwargs) def get_form(self, *args): """ Gets the form for the view. Includes all form fields given by the - tab's config objects. + config collection. """ form = super(ConfigView, self).get_form(*args) - for name, field in self.generate_form_fields_from_config_page(): + for name, field in self.generate_form_fields_from_config_collection(): form.fields[name] = field return form - def generate_form_fields_from_config_page(self): + def generate_form_fields_from_config_collection(self): """ Generates the fields for the get_form function. """ - for variable in self.config_page.variables: + for variable in self.config_collection.variables: if variable.form_field is not None: yield (variable.name, variable.form_field) @@ -51,54 +51,55 @@ class ConfigView(FormView): as intial value for the form. """ initial = super(ConfigView, self).get_initial() - for variable in self.config_page.variables: + for variable in self.config_collection.variables: initial.update({variable.name: config[variable.name]}) return initial def get_context_data(self, **kwargs): """ - Adds to the context the active config tab, a list of dictionaries - containing all config tabs each with a flag which is true if the - tab is the active one and adds a flag whether the config page has - groups. Adds also extra_stylefiles and extra_javascript. + Adds to the context the active config view, a list of dictionaries + containing all config collections each with a flag which is true if its + view is the active one and adds a flag whether the config collection + has groups. Adds also extra_stylefiles and extra_javascript. """ context = super(ConfigView, self).get_context_data(**kwargs) - context['active_config_page'] = self.config_page + context['active_config_collection_view'] = self.config_collection - config_pages_list = [] - for receiver, config_page in config_signal.send(sender=self): - if config_page.is_shown(): - config_pages_list.append({ - 'config_page': config_page, - 'active': self.request.path == reverse('config_%s' % config_page.url)}) - context['config_pages_list'] = sorted(config_pages_list, key=lambda config_page_dict: config_page_dict['config_page'].weight) + config_collection_list = [] + for receiver, config_collection in config_signal.send(sender=self): + if config_collection.is_shown(): + config_collection_list.append({ + 'config_collection': config_collection, + 'active': self.request.path == reverse('config_%s' % config_collection.url)}) + context['config_collection_list'] = sorted( + config_collection_list, key=lambda config_collection_dict: config_collection_dict['config_collection'].weight) - if hasattr(self.config_page, 'groups'): - context['groups'] = self.config_page.groups + if hasattr(self.config_collection, 'groups'): + context['groups'] = self.config_collection.groups else: context['groups'] = None - if 'extra_stylefiles' in self.config_page.extra_context: + if 'extra_stylefiles' in self.config_collection.extra_context: if 'extra_stylefiles' in context: - context['extra_stylefiles'].extend(self.config_page.extra_context['extra_stylefiles']) + context['extra_stylefiles'].extend(self.config_collection.extra_context['extra_stylefiles']) else: - context['extra_stylefiles'] = self.config_page.extra_context['extra_stylefiles'] + context['extra_stylefiles'] = self.config_collection.extra_context['extra_stylefiles'] - if 'extra_javascript' in self.config_page.extra_context: + if 'extra_javascript' in self.config_collection.extra_context: if 'extra_javascript' in context: - context['extra_javascript'].extend(self.config_page.extra_context['extra_javascript']) + context['extra_javascript'].extend(self.config_collection.extra_context['extra_javascript']) else: - context['extra_javascript'] = self.config_page.extra_context['extra_javascript'] + context['extra_javascript'] = self.config_collection.extra_context['extra_javascript'] return context def get_success_url(self): """ Returns the success url when changes are saved. Here it is the same - url as the tab. + url as the main menu entry. """ - return reverse('config_%s' % self.config_page.url) + return reverse('config_%s' % self.config_collection.url) def form_valid(self, form): """ @@ -106,17 +107,17 @@ class ConfigView(FormView): """ for key in form.cleaned_data: config[key] = form.cleaned_data[key] - messages.success(self.request, _('%s settings successfully saved.') % _(self.config_page.title)) + messages.success(self.request, _('%s settings successfully saved.') % _(self.config_collection.title)) return super(ConfigView, self).form_valid(form) def register_tab(request): """ - Registers the tab for this app in the main menu. + Registers the entry for this app in the main menu. """ return Tab( title=_('Configuration'), app='config', - url=reverse('config_first_config_page'), + url=reverse('config_first_config_collection_view'), permission=request.user.has_perm('config.can_manage'), selected=request.path.startswith('/config/')) diff --git a/openslides/core/signals.py b/openslides/core/signals.py index d77f43986..d44afac12 100644 --- a/openslides/core/signals.py +++ b/openslides/core/signals.py @@ -5,15 +5,15 @@ from django.dispatch import receiver, Signal from django.utils.translation import ugettext as _ from django.utils.translation import ugettext_lazy, ugettext_noop -from openslides.config.api import ConfigGroup, ConfigGroupedPage, ConfigVariable +from openslides.config.api import ConfigGroup, ConfigGroupedCollection, ConfigVariable from openslides.config.signals import config_signal from openslides.projector.api import update_projector post_database_setup = Signal() -@receiver(config_signal, dispatch_uid='setup_general_config_page') -def setup_general_config_page(sender, **kwargs): +@receiver(config_signal, dispatch_uid='setup_general_config') +def setup_general_config(sender, **kwargs): """ General config variables for OpenSlides. They are grouped in 'Event', 'Welcome Widget' and 'System'. @@ -182,7 +182,7 @@ def setup_general_config_page(sender, **kwargs): title=ugettext_lazy('System'), variables=(system_enable_anonymous, system_url, system_wlan_ssid, system_wlan_password, system_wlan_encryption)) - return ConfigGroupedPage( + return ConfigGroupedCollection( title=ugettext_noop('General'), url='general', required_permission='config.can_manage', diff --git a/openslides/motion/signals.py b/openslides/motion/signals.py index 209a91f05..b581d6530 100644 --- a/openslides/motion/signals.py +++ b/openslides/motion/signals.py @@ -5,15 +5,15 @@ from django.dispatch import receiver from django.utils.translation import ugettext as _ from django.utils.translation import ugettext_lazy, ugettext_noop -from openslides.config.api import ConfigPage, ConfigVariable +from openslides.config.api import ConfigCollection, ConfigVariable from openslides.config.signals import config_signal from openslides.core.signals import post_database_setup from .models import State, Workflow -@receiver(config_signal, dispatch_uid='setup_motion_config_page') -def setup_motion_config_page(sender, **kwargs): +@receiver(config_signal, dispatch_uid='setup_motion_config') +def setup_motion_config(sender, **kwargs): """ Motion config variables. """ @@ -109,22 +109,22 @@ def setup_motion_config_page(sender, **kwargs): ('serially_numbered', ugettext_lazy('Serially numbered')), ('manually', ugettext_lazy('Set it manually'))])) - return ConfigPage(title=ugettext_noop('Motion'), - url='motion', - required_permission='config.can_manage', - weight=30, - variables=(motion_stop_submitting, - motion_min_supporters, - motion_remove_supporters, - motion_preamble, - motion_pdf_ballot_papers_selection, - motion_pdf_ballot_papers_number, - motion_pdf_title, - motion_pdf_preamble, - motion_pdf_paragraph_numbering, - motion_allow_disable_versioning, - motion_workflow, - motion_identifier)) + return ConfigCollection(title=ugettext_noop('Motion'), + url='motion', + required_permission='config.can_manage', + weight=30, + variables=(motion_stop_submitting, + motion_min_supporters, + motion_remove_supporters, + motion_preamble, + motion_pdf_ballot_papers_selection, + motion_pdf_ballot_papers_number, + motion_pdf_title, + motion_pdf_preamble, + motion_pdf_paragraph_numbering, + motion_allow_disable_versioning, + motion_workflow, + motion_identifier)) @receiver(post_database_setup, dispatch_uid='motion_create_builtin_workflows') diff --git a/openslides/participant/signals.py b/openslides/participant/signals.py index 95f58cb71..54cafa5c1 100644 --- a/openslides/participant/signals.py +++ b/openslides/participant/signals.py @@ -7,7 +7,7 @@ from django.dispatch import receiver from django.utils.translation import ugettext as _ from django.utils.translation import ugettext_lazy, ugettext_noop -from openslides.config.api import ConfigPage, ConfigVariable +from openslides.config.api import ConfigCollection, ConfigVariable from openslides.config.signals import config_signal from openslides.core.signals import post_database_setup @@ -15,8 +15,8 @@ from .api import create_or_reset_admin_user from .models import Group -@receiver(config_signal, dispatch_uid='setup_participant_config_page') -def setup_participant_config_page(sender, **kwargs): +@receiver(config_signal, dispatch_uid='setup_participant_config') +def setup_participant_config(sender, **kwargs): """ Participant config variables. """ @@ -44,13 +44,13 @@ def setup_participant_config_page(sender, **kwargs): label=ugettext_lazy('Sort participants by first name'), help_text=ugettext_lazy('Disable for sorting by last name'))) - return ConfigPage(title=ugettext_noop('Participant'), - url='participant', - required_permission='config.can_manage', - weight=50, - variables=(participant_pdf_welcometitle, - participant_pdf_welcometext, - participant_sort_users_by_first_name)) + return ConfigCollection(title=ugettext_noop('Participant'), + url='participant', + required_permission='config.can_manage', + weight=50, + variables=(participant_pdf_welcometitle, + participant_pdf_welcometext, + participant_sort_users_by_first_name)) @receiver(post_database_setup, dispatch_uid='participant_create_builtin_groups_and_admin') diff --git a/openslides/projector/signals.py b/openslides/projector/signals.py index 34b8155b4..9c2d061f9 100644 --- a/openslides/projector/signals.py +++ b/openslides/projector/signals.py @@ -7,7 +7,7 @@ from django.dispatch import receiver, Signal from django.template.loader import render_to_string from django.utils.datastructures import SortedDict -from openslides.config.api import config, ConfigPage, ConfigVariable +from openslides.config.api import config, ConfigCollection, ConfigVariable from openslides.config.signals import config_signal from .projector import Overlay @@ -15,13 +15,12 @@ from .projector import Overlay projector_overlays = Signal(providing_args=['request']) -@receiver(config_signal, dispatch_uid='setup_projector_config_variables') -def config_variables(sender, **kwargs): +@receiver(config_signal, dispatch_uid='setup_projector_config') +def setup_projector_config(sender, **kwargs): """ Projector config variables for OpenSlides. They are not shown on a - config page. + config view. """ - # The active slide. The config-value is a dictonary with at least the entry # 'callback'. projector = ConfigVariable( @@ -68,8 +67,8 @@ def config_variables(sender, **kwargs): name='pdf_fullscreen', default_value=False) - return ConfigPage( - title='No title here', url='bar', required_permission=None, variables=( + return ConfigCollection( + required_permission=None, variables=( projector, projector_message, countdown_time, countdown_start_stamp, countdown_pause_stamp, countdown_state, projector_scale, projector_scroll, diff --git a/tests/agenda/tests.py b/tests/agenda/tests.py index 821c2bbe9..099043d7b 100644 --- a/tests/agenda/tests.py +++ b/tests/agenda/tests.py @@ -277,7 +277,7 @@ class ConfigTest(TestCase): self.client = Client() self.client.login(username='config_test_admin', password='default') - def test_config_page_css_javascript(self): + def test_config_collection_css_javascript(self): response = self.client.get('/config/agenda/') self.assertContains(response, 'timepicker.css', status_code=200) self.assertContains(response, 'jquery-ui-timepicker-addon.min.js', status_code=200) diff --git a/tests/config/test_config.py b/tests/config/test_config.py index bb7dd79a4..7f3d1565c 100644 --- a/tests/config/test_config.py +++ b/tests/config/test_config.py @@ -7,8 +7,8 @@ from django.dispatch import receiver from django.test.client import Client from mock import patch -from openslides.config.api import (config, ConfigGroup, ConfigGroupedPage, - ConfigPage, ConfigVariable) +from openslides.config.api import (config, ConfigCollection, ConfigGroup, + ConfigGroupedCollection, ConfigVariable) from openslides.config.exceptions import ConfigError, ConfigNotFound from openslides.config.signals import config_signal from openslides.participant.models import User @@ -34,11 +34,11 @@ class HandleConfigTest(TestCase): callable_obj=self.get_config_var, key='unknown_config_var') def test_get_multiple_config_var_error(self): - config_signal.connect(set_simple_config_page_multiple_vars, dispatch_uid='set_simple_config_page_multiple_vars_for_testing') + config_signal.connect(set_simple_config_view_multiple_vars, dispatch_uid='set_simple_config_view_multiple_vars_for_testing') self.assertRaisesMessage(expected_exception=ConfigError, expected_message='Too many values for config variable multiple_config_var found.', callable_obj=config.setup_cache) - config_signal.disconnect(set_simple_config_page_multiple_vars, dispatch_uid='set_simple_config_page_multiple_vars_for_testing') + config_signal.disconnect(set_simple_config_view_multiple_vars, dispatch_uid='set_simple_config_view_multiple_vars_for_testing') def test_database_queries(self): """ @@ -187,12 +187,50 @@ class ConfigFormTest(TestCase): {'integer_var': 'bad_string_value'}) self.assertContains(response=response, text='errorlist', status_code=200) - def test_disabled_config_page(self): + def test_disabled_config_view(self): response = self.client_manager.get('/config/testsimplepage3/') self.assertEqual(response.status_code, 404) response = self.client_manager.get('/config/testgroupedpage1/') self.assertNotContains(response=response, text='Ho5iengaoon5Hoht', status_code=200) + def test_improperly_configured_config_view(self): + from openslides.config import urls + collection = ConfigCollection( + title='Only a small title but no url ci6xahb8Chula0Thesho', + variables=(ConfigVariable(name='some_var_paiji9theiW8ooXivae6', + default_value='', + form_field=forms.CharField()),)) + + def setup_bad_config_view_one(sender, **kwargs): + return collection + + config_signal.connect(setup_bad_config_view_one, dispatch_uid='setup_bad_config_view_one_for_testing') + self.assertRaisesMessage( + ConfigError, + 'The config collection %s must have a title and an url attribute.' % repr(collection), + reload, + urls) + config_signal.disconnect(setup_bad_config_view_one, dispatch_uid='setup_bad_config_view_one_for_testing') + + def test_improperly_configured_config_view_two(self): + from openslides.config import urls + collection = ConfigCollection( + url='only_url_ureiraeY1Oochuad7xei', + variables=(ConfigVariable(name='some_var_vuuC6eiXeiyae3ik4gie', + default_value='', + form_field=forms.CharField()),)) + + def setup_bad_config_view_two(sender, **kwargs): + return collection + + config_signal.connect(setup_bad_config_view_two, dispatch_uid='setup_bad_config_view_twoe_for_testing') + self.assertRaisesMessage( + ConfigError, + 'The config collection %s must have a title and an url attribute.' % repr(collection), + reload, + urls) + config_signal.disconnect(setup_bad_config_view_two, dispatch_uid='setup_bad_config_view_twoe_for_testing') + def test_extra_stylefiles(self): response = self.client_manager.get('/config/testgroupedpage1/') text = '' @@ -232,24 +270,24 @@ class ConfigWeightTest(TestCase): self.client_manager = Client() self.client_manager.login(username='config_test_manager', password='default') - def test_order_of_config_pages_abstract(self): - config_page_dict = {} - for receiver, config_page in config_signal.send(sender=self): - config_page_dict[receiver.__name__] = config_page - self.assertGreater(config_page_dict['set_grouped_config_page'].weight, config_page_dict['set_simple_config_page'].weight) + def test_order_of_config_views_abstract(self): + config_collection_dict = {} + for receiver, config_collection in config_signal.send(sender=self): + config_collection_dict[receiver.__name__] = config_collection + self.assertGreater(config_collection_dict['set_grouped_config_view'].weight, config_collection_dict['set_simple_config_view'].weight) - def test_order_of_config_pages_on_view(self): + def test_order_of_config_collections_on_view(self): response = self.client_manager.get('/config/testgroupedpage1/') import re - m1 = re.search('Config vars for testing 1', response.content) - m2 = re.search('Config vars for testing 2', response.content) + m1 = re.search('\s*Config vars for testing 1\s*', response.content) + m2 = re.search('\s*Config vars for testing 2\s*', response.content) self.assertGreater(m1.start(), m2.start()) -@receiver(config_signal, dispatch_uid='set_grouped_config_page_for_testing') -def set_grouped_config_page(sender, **kwargs): +@receiver(config_signal, dispatch_uid='set_grouped_config_view_for_testing') +def set_grouped_config_view(sender, **kwargs): """ - Sets a grouped config page which can be reached under the url + Sets a grouped config collection view which can be reached under the url '/config/testgroupedpage1/'. There are some variables, one variable with a string as default value, one with a boolean as default value, one with an integer as default value, one with choices and one @@ -278,57 +316,62 @@ def set_grouped_config_page(sender, **kwargs): form_field=forms.ChoiceField(choices=((1, 'Choice One Ughoch4ocoche6Ee'), (2, 'Choice Two Vahnoh5yalohv5Eb')))) group_2 = ConfigGroup(title='Group 2 Toongai7ahyahy7B', variables=(hidden_var, choices_var)) - return ConfigGroupedPage(title='Config vars for testing 1', - url='testgroupedpage1', - required_permission='config.can_manage', - weight=10000, - groups=(group_1, group_2), - extra_context={'extra_stylefiles': ['styles/test-config-sjNN56dFGDrg2.css'], - 'extra_javascript': ['javascript/test-config-djg4dFGVslk4209f.js']}) + return ConfigGroupedCollection( + title='Config vars for testing 1', + url='testgroupedpage1', + required_permission='config.can_manage', + weight=10000, + groups=(group_1, group_2), + extra_context={'extra_stylefiles': ['styles/test-config-sjNN56dFGDrg2.css'], + 'extra_javascript': ['javascript/test-config-djg4dFGVslk4209f.js']}) -@receiver(config_signal, dispatch_uid='set_simple_config_page_for_testing') -def set_simple_config_page(sender, **kwargs): +@receiver(config_signal, dispatch_uid='set_simple_config_view_for_testing') +def set_simple_config_view(sender, **kwargs): """ - Sets a simple config page with some config variables but without + Sets a simple config view with some config variables but without grouping. """ - return ConfigPage(title='Config vars for testing 2', - url='testsimplepage1', - required_permission='No permission required', - variables=(ConfigVariable(name='additional_config_var', default_value='BaeB0ahcMae3feem'), - ConfigVariable(name='additional_config_var_2', default_value='', form_field=forms.CharField()), - ConfigVariable(name='none_config_var', default_value=None))) + return ConfigCollection( + title='Config vars for testing 2', + url='testsimplepage1', + required_permission='No permission required', + variables=(ConfigVariable(name='additional_config_var', default_value='BaeB0ahcMae3feem'), + ConfigVariable(name='additional_config_var_2', default_value='', form_field=forms.CharField()), + ConfigVariable(name='none_config_var', default_value=None))) # Do not connect to the signal now but later inside the test. -def set_simple_config_page_multiple_vars(sender, **kwargs): +def set_simple_config_view_multiple_vars(sender, **kwargs): """ - Sets a bad config page with some multiple config vars. + Sets a bad config view with some multiple config vars. """ - return ConfigPage(title='Config vars for testing 3', - url='testsimplepage2', - required_permission='No permission required', - variables=(ConfigVariable(name='multiple_config_var', default_value='foobar1'), - ConfigVariable(name='multiple_config_var', default_value='foobar2'))) + return ConfigCollection( + title='Config vars for testing 3', + url='testsimplepage2', + required_permission='No permission required', + variables=(ConfigVariable(name='multiple_config_var', default_value='foobar1'), + ConfigVariable(name='multiple_config_var', default_value='foobar2'))) -@receiver(config_signal, dispatch_uid='set_simple_config_page_disabled_page_for_testing') -def set_simple_config_page_disabled_page(sender, **kwargs): - return ConfigPage(title='Ho5iengaoon5Hoht', - url='testsimplepage3', - required_permission='No permission required', - variables=(ConfigVariable(name='hidden_config_var_2', default_value=''),)) +@receiver(config_signal, dispatch_uid='set_simple_config_collection_disabled_view_for_testing') +def set_simple_config_collection_disabled_view(sender, **kwargs): + return ConfigCollection( + title='Ho5iengaoon5Hoht', + url='testsimplepage3', + required_permission='No permission required', + variables=(ConfigVariable(name='hidden_config_var_2', default_value=''),)) -@receiver(config_signal, dispatch_uid='set_simple_config_page_with_callback_for_testing') -def set_simple_config_page_with_callback(sender, **kwargs): +@receiver(config_signal, dispatch_uid='set_simple_config_collection_with_callback_for_testing') +def set_simple_config_collection_with_callback(sender, **kwargs): def callback(): raise Exception('Change callback dhcnfg34dlg06kdg successfully called.') - return ConfigPage(title='Hvndfhsbgkridfgdfg', - url='testsimplepage4', - required_permission='No permission required', - variables=(ConfigVariable( - name='var_with_callback_ghvnfjd5768gdfkwg0hm2', - default_value='', - on_change=callback),)) + return ConfigCollection( + title='Hvndfhsbgkridfgdfg', + url='testsimplepage4', + required_permission='No permission required', + variables=(ConfigVariable( + name='var_with_callback_ghvnfjd5768gdfkwg0hm2', + default_value='', + on_change=callback),))