Moved config app into the core app
This commit is contained in:
parent
bcfe72fa8c
commit
e042c668d5
@ -37,7 +37,7 @@ Other:
|
||||
- Refactored projector API using metaclasses now.
|
||||
- Renamed SignalConnectMetaClass classmethod get_all_objects to get_all
|
||||
(private API).
|
||||
- Refactored config API.
|
||||
- Refactored config API and moved it into the core app.
|
||||
- Removed old style personal info page, main menu entries and widget API.
|
||||
- Used AngularJS with additional libraries for single page frontend.
|
||||
- Removed use of 'django.views.i18n.javascript_catalog'. Used angular-gettext
|
||||
|
@ -12,7 +12,7 @@ class AgendaAppConfig(AppConfig):
|
||||
|
||||
# Import all required stuff.
|
||||
from django.db.models.signals import pre_delete
|
||||
from openslides.config.signals import config_signal
|
||||
from openslides.core.signals import config_signal
|
||||
from openslides.utils.rest_api import router
|
||||
from .signals import setup_agenda_config, listen_to_related_object_delete_signal
|
||||
from .views import ItemViewSet
|
||||
|
@ -9,12 +9,12 @@ from django.db import models
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import ugettext_lazy, ugettext_noop
|
||||
|
||||
from openslides.config.api import config
|
||||
from openslides.core.config import config
|
||||
from openslides.core.models import Tag
|
||||
from openslides.projector.models import SlideMixin
|
||||
from openslides.users.models import User
|
||||
from openslides.utils.exceptions import OpenSlidesError
|
||||
from openslides.utils.rest_api import RESTModelMixin
|
||||
from openslides.utils.models import RESTModelMixin
|
||||
from openslides.utils.utils import to_roman
|
||||
|
||||
|
||||
|
@ -6,7 +6,7 @@ from django.core.validators import MaxLengthValidator, MinValueValidator
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
from openslides.config.api import ConfigVariable
|
||||
from openslides.core.config import ConfigVariable
|
||||
|
||||
from .models import Item
|
||||
|
||||
@ -22,7 +22,7 @@ def setup_agenda_config(sender, **kwargs):
|
||||
"""
|
||||
Receiver function to setup all agenda config variables. They are not
|
||||
grouped. This function connected to the signal
|
||||
openslides.config.signals.config_signal during app loading.
|
||||
openslides.core.signals.config_signal during app loading.
|
||||
"""
|
||||
# TODO: Use an input type with generic datetime support.
|
||||
yield ConfigVariable(
|
||||
|
@ -11,7 +11,7 @@ class AssignmentAppConfig(AppConfig):
|
||||
from . import projector # noqa
|
||||
|
||||
# Import all required stuff.
|
||||
from openslides.config.signals import config_signal
|
||||
from openslides.core.signals import config_signal
|
||||
from openslides.utils.rest_api import router
|
||||
from .signals import setup_assignment_config
|
||||
from .views import AssignmentViewSet, AssignmentPollViewSet
|
||||
|
@ -5,7 +5,7 @@ from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import ugettext_lazy, ugettext_noop
|
||||
|
||||
from openslides.agenda.models import Item, Speaker
|
||||
from openslides.config.api import config
|
||||
from openslides.core.config import config
|
||||
from openslides.core.models import Tag
|
||||
from openslides.poll.models import (
|
||||
BaseOption,
|
||||
@ -17,7 +17,7 @@ from openslides.poll.models import (
|
||||
from openslides.projector.models import SlideMixin
|
||||
from openslides.users.models import User
|
||||
from openslides.utils.exceptions import OpenSlidesError
|
||||
from openslides.utils.rest_api import RESTModelMixin
|
||||
from openslides.utils.models import RESTModelMixin
|
||||
|
||||
|
||||
class AssignmentRelatedUser(RESTModelMixin, models.Model):
|
||||
|
@ -2,7 +2,7 @@ from django.core.validators import MinValueValidator
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
from openslides.config.api import ConfigVariable
|
||||
from openslides.core.config import ConfigVariable
|
||||
from openslides.poll.models import PERCENT_BASE_CHOICES
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ def setup_assignment_config(sender, **kwargs):
|
||||
"""
|
||||
Receiver function to setup all assignment config variables. They are
|
||||
grouped in 'Ballot and ballot papers' and 'PDF'. This function is
|
||||
connected to the signal openslides.config.signals.config_signal during
|
||||
connected to the signal openslides.core.signals.config_signal during
|
||||
app loading.
|
||||
"""
|
||||
# Ballot and ballot papers
|
||||
|
@ -15,7 +15,7 @@ from reportlab.platypus import (
|
||||
TableStyle,
|
||||
)
|
||||
|
||||
from openslides.config.api import config
|
||||
from openslides.core.config import config
|
||||
from openslides.users.models import Group, User # TODO: remove this
|
||||
from openslides.utils.pdf import stylesheet
|
||||
from openslides.utils.rest_api import (
|
||||
|
@ -1 +0,0 @@
|
||||
default_app_config = 'openslides.config.apps.ConfigAppConfig'
|
@ -1,14 +0,0 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class ConfigAppConfig(AppConfig):
|
||||
name = 'openslides.config'
|
||||
verbose_name = 'OpenSlides Config'
|
||||
|
||||
def ready(self):
|
||||
# Import all required stuff.
|
||||
from openslides.utils.rest_api import router
|
||||
from .views import ConfigViewSet
|
||||
|
||||
# Register viewsets.
|
||||
router.register('config/config', ConfigViewSet, 'config')
|
@ -1,9 +0,0 @@
|
||||
from openslides.utils.exceptions import OpenSlidesError
|
||||
|
||||
|
||||
class ConfigError(OpenSlidesError):
|
||||
pass
|
||||
|
||||
|
||||
class ConfigNotFound(ConfigError):
|
||||
pass
|
@ -1,18 +0,0 @@
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_noop
|
||||
from jsonfield import JSONField
|
||||
|
||||
|
||||
class ConfigStore(models.Model):
|
||||
"""
|
||||
A model class to store all config variables in the database.
|
||||
"""
|
||||
|
||||
key = models.CharField(max_length=255, unique=True, db_index=True)
|
||||
"""A string, the key of the config variable."""
|
||||
|
||||
value = JSONField()
|
||||
"""The value of the config variable. """
|
||||
|
||||
class Meta:
|
||||
permissions = (('can_manage', ugettext_noop('Can manage configuration')),)
|
@ -1,4 +0,0 @@
|
||||
from django.dispatch import Signal
|
||||
|
||||
config_signal = Signal(providing_args=[])
|
||||
"""Signal to get all config tabs from all apps."""
|
@ -1,89 +0,0 @@
|
||||
from collections import OrderedDict
|
||||
from operator import attrgetter
|
||||
|
||||
from django.http import Http404
|
||||
|
||||
from openslides.utils.rest_api import (
|
||||
Response,
|
||||
SimpleMetadata,
|
||||
ValidationError,
|
||||
ViewSet,
|
||||
)
|
||||
|
||||
from .api import config
|
||||
from .exceptions import ConfigError, ConfigNotFound
|
||||
|
||||
|
||||
class ConfigMetadata(SimpleMetadata):
|
||||
"""
|
||||
Custom metadata class to add config info to responses on OPTIONS requests.
|
||||
"""
|
||||
def determine_metadata(self, request, view):
|
||||
# Sort config variables by weight.
|
||||
config_variables = sorted(config.get_config_variables().values(), key=attrgetter('weight'))
|
||||
|
||||
# Build tree.
|
||||
config_groups = []
|
||||
for config_variable in config_variables:
|
||||
if not config_groups or config_groups[-1]['name'] != config_variable.group:
|
||||
config_groups.append(OrderedDict(
|
||||
name=config_variable.group,
|
||||
subgroups=[]))
|
||||
if not config_groups[-1]['subgroups'] or config_groups[-1]['subgroups'][-1]['name'] != config_variable.subgroup:
|
||||
config_groups[-1]['subgroups'].append(OrderedDict(
|
||||
name=config_variable.subgroup,
|
||||
items=[]))
|
||||
config_groups[-1]['subgroups'][-1]['items'].append(config_variable.data)
|
||||
|
||||
# Add tree to metadata.
|
||||
metadata = super().determine_metadata(request, view)
|
||||
metadata['config_groups'] = config_groups
|
||||
return metadata
|
||||
|
||||
|
||||
class ConfigViewSet(ViewSet):
|
||||
"""
|
||||
API endpoint to list, retrieve and update the config.
|
||||
"""
|
||||
metadata_class = ConfigMetadata
|
||||
|
||||
def list(self, request):
|
||||
"""
|
||||
Lists all config variables. Everybody can see them.
|
||||
"""
|
||||
return Response([{'key': key, 'value': value} for key, value in config.items()])
|
||||
|
||||
def retrieve(self, request, *args, **kwargs):
|
||||
"""
|
||||
Retrieves a config variable. Everybody can see it.
|
||||
"""
|
||||
key = kwargs['pk']
|
||||
try:
|
||||
value = config[key]
|
||||
except ConfigNotFound:
|
||||
raise Http404
|
||||
return Response({'key': key, 'value': value})
|
||||
|
||||
def update(self, request, *args, **kwargs):
|
||||
"""
|
||||
Updates a config variable. Only managers can do this.
|
||||
|
||||
Example: {"value": 42}
|
||||
"""
|
||||
# Check permission.
|
||||
if not request.user.has_perm('config.can_manage'):
|
||||
self.permission_denied(request)
|
||||
|
||||
key = kwargs['pk']
|
||||
value = request.data['value']
|
||||
|
||||
# Validate and change value.
|
||||
try:
|
||||
config[key] = value
|
||||
except ConfigNotFound:
|
||||
raise Http404
|
||||
except ConfigError as e:
|
||||
raise ValidationError({'detail': e})
|
||||
|
||||
# Return response.
|
||||
return Response({'key': key, 'value': value})
|
@ -12,11 +12,16 @@ class CoreAppConfig(AppConfig):
|
||||
|
||||
# Import all required stuff.
|
||||
from django.db.models import signals
|
||||
from openslides.config.signals import config_signal
|
||||
from openslides.core.signals import config_signal
|
||||
from openslides.utils.autoupdate import inform_changed_data_receiver
|
||||
from openslides.utils.rest_api import router
|
||||
from .signals import setup_general_config
|
||||
from .views import CustomSlideViewSet, ProjectorViewSet, TagViewSet
|
||||
from .views import (
|
||||
ConfigViewSet,
|
||||
CustomSlideViewSet,
|
||||
ProjectorViewSet,
|
||||
TagViewSet,
|
||||
)
|
||||
|
||||
# Connect signals.
|
||||
config_signal.connect(setup_general_config, dispatch_uid='setup_general_config')
|
||||
@ -25,6 +30,7 @@ class CoreAppConfig(AppConfig):
|
||||
router.register('core/projector', ProjectorViewSet)
|
||||
router.register('core/customslide', CustomSlideViewSet)
|
||||
router.register('core/tag', TagViewSet)
|
||||
router.register('core/config', ConfigViewSet, 'config')
|
||||
|
||||
# Update data when any model of any installed app is saved or deleted.
|
||||
# TODO: Test if the m2m_changed signal is also needed.
|
||||
|
@ -3,7 +3,6 @@ from django.utils.translation import ugettext as _
|
||||
|
||||
from .exceptions import ConfigError, ConfigNotFound
|
||||
from .models import ConfigStore
|
||||
from .signals import config_signal
|
||||
|
||||
INPUT_TYPE_MAPPING = {
|
||||
'string': str,
|
||||
@ -97,6 +96,10 @@ class ConfigHandler:
|
||||
Returns a dictionary with all ConfigVariable instances of all
|
||||
signal receivers. The key is the name of the config variable.
|
||||
"""
|
||||
# config_signal can not be imported at global space, because
|
||||
# core.signals imports this file
|
||||
from .signals import config_signal
|
||||
|
||||
result = {}
|
||||
for receiver, config_collection in config_signal.send(sender='get_config_variables'):
|
||||
for config_variable in config_collection:
|
@ -7,3 +7,11 @@ class ProjectorException(OpenSlidesError):
|
||||
|
||||
class TagException(OpenSlidesError):
|
||||
pass
|
||||
|
||||
|
||||
class ConfigError(OpenSlidesError):
|
||||
pass
|
||||
|
||||
|
||||
class ConfigNotFound(ConfigError):
|
||||
pass
|
||||
|
@ -1,4 +1,4 @@
|
||||
from openslides.config.api import config
|
||||
from .config import config
|
||||
|
||||
|
||||
class ConfigCacheMiddleware(object):
|
@ -2,7 +2,6 @@ import jsonfield.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
import openslides.utils.models
|
||||
import openslides.utils.rest_api
|
||||
|
||||
|
||||
def add_default_projector(apps, schema_editor):
|
||||
@ -32,20 +31,20 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='CustomSlide',
|
||||
fields=[
|
||||
('id', models.AutoField(serialize=False, primary_key=True, auto_created=True, verbose_name='ID')),
|
||||
('title', models.CharField(verbose_name='Title', max_length=256)),
|
||||
('text', models.TextField(verbose_name='Text', blank=True)),
|
||||
('id', models.AutoField(auto_created=True, serialize=False, verbose_name='ID', primary_key=True)),
|
||||
('title', models.CharField(max_length=256, verbose_name='Title')),
|
||||
('text', models.TextField(blank=True, verbose_name='Text')),
|
||||
('weight', models.IntegerField(verbose_name='Weight', default=0)),
|
||||
],
|
||||
options={
|
||||
'ordering': ('weight', 'title'),
|
||||
},
|
||||
bases=(openslides.utils.rest_api.RESTModelMixin, models.Model),
|
||||
bases=(openslides.utils.models.RESTModelMixin, models.Model),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Projector',
|
||||
fields=[
|
||||
('id', models.AutoField(serialize=False, primary_key=True, auto_created=True, verbose_name='ID')),
|
||||
('id', models.AutoField(auto_created=True, serialize=False, verbose_name='ID', primary_key=True)),
|
||||
('config', jsonfield.fields.JSONField()),
|
||||
],
|
||||
options={
|
||||
@ -55,21 +54,35 @@ class Migration(migrations.Migration):
|
||||
('can_see_dashboard', 'Can see the dashboard'),
|
||||
('can_use_chat', 'Can use the chat')),
|
||||
},
|
||||
bases=(openslides.utils.rest_api.RESTModelMixin, models.Model),
|
||||
bases=(openslides.utils.models.RESTModelMixin, models.Model),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Tag',
|
||||
fields=[
|
||||
('id', models.AutoField(serialize=False, primary_key=True, auto_created=True, verbose_name='ID')),
|
||||
('name', models.CharField(verbose_name='Tag', unique=True, max_length=255)),
|
||||
('id', models.AutoField(auto_created=True, serialize=False, verbose_name='ID', primary_key=True)),
|
||||
('name', models.CharField(max_length=255, verbose_name='Tag', unique=True)),
|
||||
],
|
||||
options={
|
||||
'permissions': (('can_manage_tags', 'Can manage tags'),),
|
||||
'ordering': ('name',),
|
||||
'permissions': (('can_manage_tags', 'Can manage tags'),),
|
||||
},
|
||||
bases=(openslides.utils.rest_api.RESTModelMixin, models.Model),
|
||||
bases=(openslides.utils.models.RESTModelMixin, models.Model),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ConfigStore',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, serialize=False, verbose_name='ID', primary_key=True)),
|
||||
('key', models.CharField(max_length=255, db_index=True, unique=True)),
|
||||
('value', jsonfield.fields.JSONField()),
|
||||
],
|
||||
options={
|
||||
'permissions': (('can_manage_config', 'Can manage configuration'),),
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
migrations.RunPython(
|
||||
add_default_projector,
|
||||
code=add_default_projector,
|
||||
reverse_code=None,
|
||||
atomic=True,
|
||||
),
|
||||
]
|
||||
|
@ -3,8 +3,8 @@ from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import ugettext_lazy, ugettext_noop
|
||||
from jsonfield import JSONField
|
||||
|
||||
from openslides.utils.models import RESTModelMixin
|
||||
from openslides.utils.projector import ProjectorElement
|
||||
from openslides.utils.rest_api import RESTModelMixin
|
||||
|
||||
from .exceptions import ProjectorException
|
||||
|
||||
@ -120,3 +120,18 @@ class Tag(RESTModelMixin, models.Model):
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class ConfigStore(models.Model):
|
||||
"""
|
||||
A model class to store all config variables in the database.
|
||||
"""
|
||||
|
||||
key = models.CharField(max_length=255, unique=True, db_index=True)
|
||||
"""A string, the key of the config variable."""
|
||||
|
||||
value = JSONField()
|
||||
"""The value of the config variable. """
|
||||
|
||||
class Meta:
|
||||
permissions = (('can_manage_config', ugettext_noop('Can manage configuration')),)
|
||||
|
@ -3,7 +3,7 @@ from django.dispatch import Signal
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
from openslides.config.api import ConfigVariable
|
||||
from openslides.core.config import ConfigVariable
|
||||
|
||||
# This signal is sent when the migrate command is done. That means it is sent
|
||||
# after post_migrate sending and creating all Permission objects. Don't use it
|
||||
@ -16,7 +16,7 @@ def setup_general_config(sender, **kwargs):
|
||||
Receiver function to setup general config variables for OpenSlides.
|
||||
There are two main groups: 'General' and 'Projector'. The group
|
||||
'General' has subgroups. This function is connected to the signal
|
||||
openslides.config.signals.config_signal during app loading.
|
||||
openslides.core.signals.config_signal during app loading.
|
||||
"""
|
||||
# General Event
|
||||
|
||||
@ -134,3 +134,7 @@ def setup_general_config(sender, **kwargs):
|
||||
weight=180,
|
||||
group=ugettext_lazy('Projector'),
|
||||
translatable=True)
|
||||
|
||||
|
||||
config_signal = Signal(providing_args=[])
|
||||
"""Signal to get all config tabs from all apps."""
|
||||
|
@ -128,9 +128,9 @@ angular.module('OpenSlidesApp.core', [])
|
||||
|
||||
.factory('Config', function(DS) {
|
||||
return DS.defineResource({
|
||||
name: 'config/config',
|
||||
name: 'core/config',
|
||||
idAttribute: 'key',
|
||||
endpoint: '/rest/config/config/'
|
||||
endpoint: '/rest/core/config/'
|
||||
});
|
||||
})
|
||||
|
||||
|
@ -1,9 +1,11 @@
|
||||
import re
|
||||
from collections import OrderedDict
|
||||
from operator import attrgetter
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.staticfiles import finders
|
||||
from django.core.urlresolvers import get_resolver
|
||||
from django.http import HttpResponse
|
||||
from django.http import Http404, HttpResponse
|
||||
|
||||
from openslides import __version__ as version
|
||||
from openslides.utils import views as utils_views
|
||||
@ -16,10 +18,14 @@ from openslides.utils.rest_api import (
|
||||
ModelViewSet,
|
||||
ReadOnlyModelViewSet,
|
||||
Response,
|
||||
SimpleMetadata,
|
||||
ValidationError,
|
||||
ViewSet,
|
||||
detail_route,
|
||||
)
|
||||
|
||||
from .config import config
|
||||
from .exceptions import ConfigError, ConfigNotFound
|
||||
from .models import CustomSlide, Projector, Tag
|
||||
from .serializers import (
|
||||
CustomSlideSerializer,
|
||||
@ -227,3 +233,78 @@ class VersionView(utils_views.APIView):
|
||||
'description': get_plugin_description(plugin),
|
||||
'version': get_plugin_version(plugin)})
|
||||
return result
|
||||
|
||||
|
||||
class ConfigMetadata(SimpleMetadata):
|
||||
"""
|
||||
Custom metadata class to add config info to responses on OPTIONS requests.
|
||||
"""
|
||||
def determine_metadata(self, request, view):
|
||||
# Sort config variables by weight.
|
||||
config_variables = sorted(config.get_config_variables().values(), key=attrgetter('weight'))
|
||||
|
||||
# Build tree.
|
||||
config_groups = []
|
||||
for config_variable in config_variables:
|
||||
if not config_groups or config_groups[-1]['name'] != config_variable.group:
|
||||
config_groups.append(OrderedDict(
|
||||
name=config_variable.group,
|
||||
subgroups=[]))
|
||||
if not config_groups[-1]['subgroups'] or config_groups[-1]['subgroups'][-1]['name'] != config_variable.subgroup:
|
||||
config_groups[-1]['subgroups'].append(OrderedDict(
|
||||
name=config_variable.subgroup,
|
||||
items=[]))
|
||||
config_groups[-1]['subgroups'][-1]['items'].append(config_variable.data)
|
||||
|
||||
# Add tree to metadata.
|
||||
metadata = super().determine_metadata(request, view)
|
||||
metadata['config_groups'] = config_groups
|
||||
return metadata
|
||||
|
||||
|
||||
class ConfigViewSet(ViewSet):
|
||||
"""
|
||||
API endpoint to list, retrieve and update the config.
|
||||
"""
|
||||
metadata_class = ConfigMetadata
|
||||
|
||||
def list(self, request):
|
||||
"""
|
||||
Lists all config variables. Everybody can see them.
|
||||
"""
|
||||
return Response([{'key': key, 'value': value} for key, value in config.items()])
|
||||
|
||||
def retrieve(self, request, *args, **kwargs):
|
||||
"""
|
||||
Retrieves a config variable. Everybody can see it.
|
||||
"""
|
||||
key = kwargs['pk']
|
||||
try:
|
||||
value = config[key]
|
||||
except ConfigNotFound:
|
||||
raise Http404
|
||||
return Response({'key': key, 'value': value})
|
||||
|
||||
def update(self, request, *args, **kwargs):
|
||||
"""
|
||||
Updates a config variable. Only managers can do this.
|
||||
|
||||
Example: {"value": 42}
|
||||
"""
|
||||
# Check permission.
|
||||
if not request.user.has_perm('core.can_manage_config'):
|
||||
self.permission_denied(request)
|
||||
|
||||
key = kwargs['pk']
|
||||
value = request.data['value']
|
||||
|
||||
# Validate and change value.
|
||||
try:
|
||||
config[key] = value
|
||||
except ConfigNotFound:
|
||||
raise Http404
|
||||
except ConfigError as e:
|
||||
raise ValidationError({'detail': e})
|
||||
|
||||
# Return response.
|
||||
return Response({'key': key, 'value': value})
|
||||
|
@ -68,7 +68,7 @@ MIDDLEWARE_CLASSES = (
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'openslides.users.auth.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'openslides.config.middleware.ConfigCacheMiddleware',
|
||||
'openslides.core.middleware.ConfigCacheMiddleware',
|
||||
)
|
||||
|
||||
ROOT_URLCONF = 'openslides.urls'
|
||||
@ -90,7 +90,6 @@ INSTALLED_APPS = (
|
||||
'openslides.motions',
|
||||
'openslides.assignments',
|
||||
'openslides.mediafiles',
|
||||
'openslides.config',
|
||||
)
|
||||
|
||||
TEMPLATE_CONTEXT_PROCESSORS = (
|
||||
|
@ -6,7 +6,7 @@ from django.utils.translation import ugettext_lazy, ugettext_noop
|
||||
|
||||
from openslides.projector.models import SlideMixin
|
||||
from openslides.users.models import User
|
||||
from openslides.utils.rest_api import RESTModelMixin
|
||||
from openslides.utils.models import RESTModelMixin
|
||||
|
||||
|
||||
class Mediafile(RESTModelMixin, SlideMixin, models.Model):
|
||||
|
@ -12,7 +12,7 @@ class MotionAppConfig(AppConfig):
|
||||
from . import projector # noqa
|
||||
|
||||
# Import all required stuff.
|
||||
from openslides.config.signals import config_signal
|
||||
from openslides.core.signals import config_signal
|
||||
from openslides.utils.rest_api import router
|
||||
from .signals import create_builtin_workflows, setup_motion_config
|
||||
from .views import CategoryViewSet, MotionViewSet, WorkflowViewSet
|
||||
|
@ -6,7 +6,7 @@ from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import ugettext_lazy, ugettext_noop
|
||||
from jsonfield import JSONField
|
||||
|
||||
from openslides.config.api import config
|
||||
from openslides.core.config import config
|
||||
from openslides.core.models import Tag
|
||||
from openslides.mediafiles.models import Mediafile
|
||||
from openslides.poll.models import (
|
||||
@ -17,7 +17,7 @@ from openslides.poll.models import (
|
||||
)
|
||||
from openslides.projector.models import SlideMixin
|
||||
from openslides.users.models import User
|
||||
from openslides.utils.rest_api import RESTModelMixin
|
||||
from openslides.utils.models import RESTModelMixin
|
||||
|
||||
from .exceptions import WorkflowError
|
||||
|
||||
|
@ -9,7 +9,7 @@ from reportlab.lib import colors
|
||||
from reportlab.lib.units import cm
|
||||
from reportlab.platypus import PageBreak, Paragraph, Spacer, Table, TableStyle
|
||||
|
||||
from openslides.config.api import config
|
||||
from openslides.core.config import config
|
||||
from openslides.users.models import Group, User # TODO: remove this line
|
||||
from openslides.utils.pdf import stylesheet
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
from django.db import transaction
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from openslides.config.api import config
|
||||
from openslides.core.config import config
|
||||
from openslides.utils.rest_api import (
|
||||
CharField,
|
||||
IntegerField,
|
||||
|
@ -2,7 +2,7 @@ from django.core.validators import MinValueValidator
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import pgettext, ugettext_lazy, ugettext_noop
|
||||
|
||||
from openslides.config.api import ConfigVariable
|
||||
from openslides.core.config import ConfigVariable
|
||||
from openslides.poll.models import PERCENT_BASE_CHOICES
|
||||
|
||||
from .models import State, Workflow
|
||||
@ -13,7 +13,7 @@ def setup_motion_config(sender, **kwargs):
|
||||
Receiver function to setup all motion config variables. They are
|
||||
grouped in 'General', 'Amendments', 'Supporters', 'Voting and ballot
|
||||
papers' and 'PDF'. This function connected to the signal
|
||||
openslides.config.signals.config_signal during app loading.
|
||||
openslides.core.signals.config_signal during app loading.
|
||||
"""
|
||||
# General
|
||||
|
||||
|
@ -6,7 +6,7 @@ from django.utils.translation import ugettext_noop
|
||||
from reportlab.platypus import SimpleDocTemplate
|
||||
from rest_framework import status
|
||||
|
||||
from openslides.config.api import config
|
||||
from openslides.core.config import config
|
||||
from openslides.utils.rest_api import (
|
||||
ModelViewSet,
|
||||
Response,
|
||||
|
@ -11,8 +11,7 @@ class UsersAppConfig(AppConfig):
|
||||
from . import projector # noqa
|
||||
|
||||
# Import all required stuff.
|
||||
from openslides.config.signals import config_signal
|
||||
from openslides.core.signals import post_permission_creation
|
||||
from openslides.core.signals import config_signal, post_permission_creation
|
||||
from openslides.utils.rest_api import router
|
||||
from .signals import create_builtin_groups_and_admin, setup_users_config
|
||||
from .views import GroupViewSet, UserViewSet
|
||||
|
@ -8,7 +8,7 @@ from django.db.models import Q
|
||||
from django.utils.functional import SimpleLazyObject
|
||||
from rest_framework.authentication import BaseAuthentication
|
||||
|
||||
from openslides.config.api import config
|
||||
from openslides.core.config import config
|
||||
|
||||
|
||||
class AnonymousUser(DjangoAnonymousUser):
|
||||
|
@ -13,9 +13,9 @@ from django.contrib.auth.models import ( # noqa
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy, ugettext_noop
|
||||
|
||||
from openslides.config.api import config
|
||||
from openslides.core.config import config
|
||||
from openslides.projector.models import SlideMixin
|
||||
from openslides.utils.rest_api import RESTModelMixin
|
||||
from openslides.utils.models import RESTModelMixin
|
||||
|
||||
from .exceptions import UserError
|
||||
|
||||
|
@ -14,7 +14,7 @@ from reportlab.platypus import (
|
||||
TableStyle,
|
||||
)
|
||||
|
||||
from openslides.config.api import config
|
||||
from openslides.core.config import config
|
||||
from openslides.utils.pdf import stylesheet
|
||||
|
||||
from .models import User
|
||||
|
@ -2,7 +2,7 @@ from django.db.models import Q
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import ugettext_lazy, ugettext_noop
|
||||
|
||||
from openslides.config.api import ConfigVariable
|
||||
from openslides.core.config import ConfigVariable
|
||||
|
||||
from .models import Group, Permission, User
|
||||
|
||||
@ -11,7 +11,7 @@ def setup_users_config(sender, **kwargs):
|
||||
"""
|
||||
Receiver function to setup all users config variables. They are grouped
|
||||
in 'Sorting' and 'PDF'. This function is connected to the signal
|
||||
openslides.config.signals.config_signal during app loading.
|
||||
openslides.core.signals.config_signal during app loading.
|
||||
"""
|
||||
|
||||
# Sorting
|
||||
@ -110,7 +110,7 @@ def create_builtin_groups_and_admin(**kwargs):
|
||||
'assignments.can_nominate_other',
|
||||
'assignments.can_nominate_self',
|
||||
'assignments.can_see',
|
||||
'config.can_manage',
|
||||
'core.can_manage_config',
|
||||
'core.can_manage_projector',
|
||||
'core.can_manage_tags',
|
||||
'core.can_see_dashboard',
|
||||
@ -171,7 +171,7 @@ def create_builtin_groups_and_admin(**kwargs):
|
||||
permission_dict['assignments.can_manage'],
|
||||
permission_dict['assignments.can_nominate_other'],
|
||||
permission_dict['assignments.can_nominate_self'],
|
||||
permission_dict['config.can_manage'],
|
||||
permission_dict['core.can_manage_config'],
|
||||
permission_dict['core.can_manage_projector'],
|
||||
permission_dict['core.can_manage_tags'],
|
||||
permission_dict['core.can_use_chat'],
|
||||
|
@ -299,7 +299,7 @@ def translate_customizable_strings(language_code):
|
||||
Translates all translatable config values and saves them into database.
|
||||
"""
|
||||
if check_for_language(language_code):
|
||||
from openslides.config.api import config
|
||||
from openslides.core.config import config
|
||||
current_language = get_language()
|
||||
activate(language_code)
|
||||
for name in config.get_all_translatable():
|
||||
|
@ -1,3 +1,4 @@
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db import models
|
||||
|
||||
|
||||
@ -14,3 +15,27 @@ class MinMaxIntegerField(models.IntegerField):
|
||||
defaults = {'min_value': self.min_value, 'max_value': self.max_value}
|
||||
defaults.update(kwargs)
|
||||
return super(MinMaxIntegerField, self).formfield(**defaults)
|
||||
|
||||
|
||||
class RESTModelMixin:
|
||||
"""
|
||||
Mixin for django models which are used in our rest api.
|
||||
"""
|
||||
|
||||
def get_root_rest_element(self):
|
||||
"""
|
||||
Returns the root rest instance.
|
||||
|
||||
Uses self as default.
|
||||
"""
|
||||
return self
|
||||
|
||||
def get_root_rest_url(self):
|
||||
"""
|
||||
Returns the detail url of the root model of this object.
|
||||
"""
|
||||
# Gets the default url-name in the same way as django rest framework
|
||||
# does in relations.HyperlinkedModelSerializer
|
||||
root_instance = self.get_root_rest_element()
|
||||
rest_url = '%s-detail' % type(root_instance)._meta.object_name.lower()
|
||||
return reverse(rest_url, args=[str(root_instance.pk)])
|
||||
|
@ -11,7 +11,7 @@ from reportlab.pdfbase import pdfmetrics
|
||||
from reportlab.pdfbase.ttfonts import TTFont
|
||||
from reportlab.rl_config import defaultPageSize
|
||||
|
||||
from openslides.config.api import config
|
||||
from openslides.core.config import config
|
||||
|
||||
# register new truetype fonts
|
||||
pdfmetrics.registerFont(TTFont(
|
||||
|
@ -1,7 +1,6 @@
|
||||
import re
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from rest_framework.decorators import detail_route # noqa
|
||||
from rest_framework.decorators import list_route # noqa
|
||||
from rest_framework.metadata import SimpleMetadata # noqa
|
||||
@ -33,30 +32,6 @@ from .exceptions import OpenSlidesError
|
||||
router = DefaultRouter()
|
||||
|
||||
|
||||
class RESTModelMixin:
|
||||
"""
|
||||
Mixin for django models which are used in our rest api.
|
||||
"""
|
||||
|
||||
def get_root_rest_element(self):
|
||||
"""
|
||||
Returns the root rest instance.
|
||||
|
||||
Uses self as default.
|
||||
"""
|
||||
return self
|
||||
|
||||
def get_root_rest_url(self):
|
||||
"""
|
||||
Returns the detail url of the root model of this object.
|
||||
"""
|
||||
# Gets the default url-name in the same way as django rest framework
|
||||
# does in relations.HyperlinkedModelSerializer
|
||||
root_instance = self.get_root_rest_element()
|
||||
rest_url = '%s-detail' % type(root_instance)._meta.object_name.lower()
|
||||
return reverse(rest_url, args=[str(root_instance.pk)])
|
||||
|
||||
|
||||
class ModelViewSet(_ModelViewSet):
|
||||
"""
|
||||
Viewset for models. Before the method check_permission is called we
|
||||
|
@ -2,7 +2,7 @@ from django.core.management import call_command
|
||||
from django.test import TestCase as _TestCase
|
||||
from django.test.runner import DiscoverRunner
|
||||
|
||||
from openslides.config.api import config
|
||||
from openslides.core.config import config
|
||||
|
||||
|
||||
class OpenSlidesDiscoverRunner(DiscoverRunner):
|
||||
|
@ -1,119 +0,0 @@
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.dispatch import receiver
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APIClient
|
||||
|
||||
from openslides.config.api import ConfigVariable, config
|
||||
from openslides.config.signals import config_signal
|
||||
from openslides.utils.rest_api import ValidationError
|
||||
from openslides.utils.test import TestCase
|
||||
|
||||
|
||||
class ConfigViewSet(TestCase):
|
||||
"""
|
||||
Tests requests to deal with config variables.
|
||||
"""
|
||||
def test_retrieve(self):
|
||||
self.client.login(username='admin', password='admin')
|
||||
config['test_var_aeW3Quahkah1phahCheo'] = 'test_value_Oovoojieme7eephaed2A'
|
||||
response = self.client.get(reverse('config-detail', args=['test_var_aeW3Quahkah1phahCheo']))
|
||||
self.assertEqual(
|
||||
response.data,
|
||||
{'key': 'test_var_aeW3Quahkah1phahCheo',
|
||||
'value': 'test_value_Oovoojieme7eephaed2A'})
|
||||
|
||||
def test_update(self):
|
||||
self.client = APIClient()
|
||||
self.client.login(username='admin', password='admin')
|
||||
response = self.client.put(
|
||||
reverse('config-detail', args=['test_var_Xeiizi7ooH8Thuk5aida']),
|
||||
{'value': 'test_value_Phohx3oopeichaiTheiw'})
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(config['test_var_Xeiizi7ooH8Thuk5aida'], 'test_value_Phohx3oopeichaiTheiw')
|
||||
|
||||
def test_update_wrong_datatype(self):
|
||||
self.client = APIClient()
|
||||
self.client.login(username='admin', password='admin')
|
||||
response = self.client.put(
|
||||
reverse('config-detail', args=['test_var_ohhii4iavoh5Phoh5ahg']),
|
||||
{'value': 'test_value_string'})
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertEqual(response.data, {'detail': "Wrong datatype. Expected <class 'int'>, got <class 'str'>."})
|
||||
|
||||
def test_update_good_choice(self):
|
||||
self.client = APIClient()
|
||||
self.client.login(username='admin', password='admin')
|
||||
response = self.client.put(
|
||||
reverse('config-detail', args=['test_var_wei0Rei9ahzooSohK1ph']),
|
||||
{'value': 'key_2_yahb2ain1aeZ1lea1Pei'})
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(config['test_var_wei0Rei9ahzooSohK1ph'], 'key_2_yahb2ain1aeZ1lea1Pei')
|
||||
|
||||
def test_update_bad_choice(self):
|
||||
self.client = APIClient()
|
||||
self.client.login(username='admin', password='admin')
|
||||
response = self.client.put(
|
||||
reverse('config-detail', args=['test_var_wei0Rei9ahzooSohK1ph']),
|
||||
{'value': 'test_value_bad_string'})
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertEqual(response.data, {'detail': 'Invalid input. Choice does not match.'})
|
||||
|
||||
def test_update_validator_ok(self):
|
||||
self.client = APIClient()
|
||||
self.client.login(username='admin', password='admin')
|
||||
response = self.client.put(
|
||||
reverse('config-detail', args=['test_var_Hi7Oje8Oith7goopeeng']),
|
||||
{'value': 'valid_string'})
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(config['test_var_Hi7Oje8Oith7goopeeng'], 'valid_string')
|
||||
|
||||
def test_update_validator_invalid(self):
|
||||
self.client = APIClient()
|
||||
self.client.login(username='admin', password='admin')
|
||||
response = self.client.put(
|
||||
reverse('config-detail', args=['test_var_Hi7Oje8Oith7goopeeng']),
|
||||
{'value': 'invalid_string'})
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertEqual(response.data, {'detail': 'Invalid input.'})
|
||||
|
||||
|
||||
def validator_for_testing(value):
|
||||
"""
|
||||
Validator for testing.
|
||||
"""
|
||||
if value == 'invalid_string':
|
||||
raise ValidationError({'detail': 'Invalid input.'})
|
||||
|
||||
|
||||
@receiver(config_signal, dispatch_uid='set_simple_config_view_integration_config_test')
|
||||
def set_simple_config_view_integration_config_test(sender, **kwargs):
|
||||
"""
|
||||
Sets a simple config view with some config variables but without
|
||||
grouping.
|
||||
"""
|
||||
yield ConfigVariable(
|
||||
name='test_var_aeW3Quahkah1phahCheo',
|
||||
default_value=None,
|
||||
label='test_label_aeNahsheu8phahk8taYo')
|
||||
|
||||
yield ConfigVariable(
|
||||
name='test_var_Xeiizi7ooH8Thuk5aida',
|
||||
default_value='')
|
||||
|
||||
yield ConfigVariable(
|
||||
name='test_var_ohhii4iavoh5Phoh5ahg',
|
||||
default_value=0,
|
||||
input_type='integer')
|
||||
|
||||
yield ConfigVariable(
|
||||
name='test_var_wei0Rei9ahzooSohK1ph',
|
||||
default_value='key_1_Queit2juchoocos2Vugh',
|
||||
input_type='choice',
|
||||
choices=(
|
||||
{'value': 'key_1_Queit2juchoocos2Vugh', 'display_name': 'label_1_Queit2juchoocos2Vugh'},
|
||||
{'value': 'key_2_yahb2ain1aeZ1lea1Pei', 'display_name': 'label_2_yahb2ain1aeZ1lea1Pei'}))
|
||||
|
||||
yield ConfigVariable(
|
||||
name='test_var_Hi7Oje8Oith7goopeeng',
|
||||
default_value='',
|
||||
validators=(validator_for_testing,))
|
@ -1,10 +1,15 @@
|
||||
import json
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.dispatch import receiver
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APIClient
|
||||
|
||||
from openslides import __version__ as version
|
||||
from openslides.core.config import ConfigVariable, config
|
||||
from openslides.core.models import CustomSlide, Projector
|
||||
from openslides.core.signals import config_signal
|
||||
from openslides.utils.rest_api import ValidationError
|
||||
from openslides.utils.test import TestCase
|
||||
|
||||
|
||||
@ -59,3 +64,113 @@ class VersionView(TestCase):
|
||||
{'verbose_name': 'Plugin tests.old.utils',
|
||||
'description': 'Description of plugin tests.old.utils',
|
||||
'version': 'unknown'}]})
|
||||
|
||||
|
||||
class ConfigViewSet(TestCase):
|
||||
"""
|
||||
Tests requests to deal with config variables.
|
||||
"""
|
||||
def test_retrieve(self):
|
||||
self.client.login(username='admin', password='admin')
|
||||
config['test_var_aeW3Quahkah1phahCheo'] = 'test_value_Oovoojieme7eephaed2A'
|
||||
response = self.client.get(reverse('config-detail', args=['test_var_aeW3Quahkah1phahCheo']))
|
||||
self.assertEqual(
|
||||
response.data,
|
||||
{'key': 'test_var_aeW3Quahkah1phahCheo',
|
||||
'value': 'test_value_Oovoojieme7eephaed2A'})
|
||||
|
||||
def test_update(self):
|
||||
self.client = APIClient()
|
||||
self.client.login(username='admin', password='admin')
|
||||
response = self.client.put(
|
||||
reverse('config-detail', args=['test_var_Xeiizi7ooH8Thuk5aida']),
|
||||
{'value': 'test_value_Phohx3oopeichaiTheiw'})
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(config['test_var_Xeiizi7ooH8Thuk5aida'], 'test_value_Phohx3oopeichaiTheiw')
|
||||
|
||||
def test_update_wrong_datatype(self):
|
||||
self.client = APIClient()
|
||||
self.client.login(username='admin', password='admin')
|
||||
response = self.client.put(
|
||||
reverse('config-detail', args=['test_var_ohhii4iavoh5Phoh5ahg']),
|
||||
{'value': 'test_value_string'})
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertEqual(response.data, {'detail': "Wrong datatype. Expected <class 'int'>, got <class 'str'>."})
|
||||
|
||||
def test_update_good_choice(self):
|
||||
self.client = APIClient()
|
||||
self.client.login(username='admin', password='admin')
|
||||
response = self.client.put(
|
||||
reverse('config-detail', args=['test_var_wei0Rei9ahzooSohK1ph']),
|
||||
{'value': 'key_2_yahb2ain1aeZ1lea1Pei'})
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(config['test_var_wei0Rei9ahzooSohK1ph'], 'key_2_yahb2ain1aeZ1lea1Pei')
|
||||
|
||||
def test_update_bad_choice(self):
|
||||
self.client = APIClient()
|
||||
self.client.login(username='admin', password='admin')
|
||||
response = self.client.put(
|
||||
reverse('config-detail', args=['test_var_wei0Rei9ahzooSohK1ph']),
|
||||
{'value': 'test_value_bad_string'})
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertEqual(response.data, {'detail': 'Invalid input. Choice does not match.'})
|
||||
|
||||
def test_update_validator_ok(self):
|
||||
self.client = APIClient()
|
||||
self.client.login(username='admin', password='admin')
|
||||
response = self.client.put(
|
||||
reverse('config-detail', args=['test_var_Hi7Oje8Oith7goopeeng']),
|
||||
{'value': 'valid_string'})
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(config['test_var_Hi7Oje8Oith7goopeeng'], 'valid_string')
|
||||
|
||||
def test_update_validator_invalid(self):
|
||||
self.client = APIClient()
|
||||
self.client.login(username='admin', password='admin')
|
||||
response = self.client.put(
|
||||
reverse('config-detail', args=['test_var_Hi7Oje8Oith7goopeeng']),
|
||||
{'value': 'invalid_string'})
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertEqual(response.data, {'detail': 'Invalid input.'})
|
||||
|
||||
|
||||
def validator_for_testing(value):
|
||||
"""
|
||||
Validator for testing.
|
||||
"""
|
||||
if value == 'invalid_string':
|
||||
raise ValidationError({'detail': 'Invalid input.'})
|
||||
|
||||
|
||||
@receiver(config_signal, dispatch_uid='set_simple_config_view_integration_config_test')
|
||||
def set_simple_config_view_integration_config_test(sender, **kwargs):
|
||||
"""
|
||||
Sets a simple config view with some config variables but without
|
||||
grouping.
|
||||
"""
|
||||
yield ConfigVariable(
|
||||
name='test_var_aeW3Quahkah1phahCheo',
|
||||
default_value=None,
|
||||
label='test_label_aeNahsheu8phahk8taYo')
|
||||
|
||||
yield ConfigVariable(
|
||||
name='test_var_Xeiizi7ooH8Thuk5aida',
|
||||
default_value='')
|
||||
|
||||
yield ConfigVariable(
|
||||
name='test_var_ohhii4iavoh5Phoh5ahg',
|
||||
default_value=0,
|
||||
input_type='integer')
|
||||
|
||||
yield ConfigVariable(
|
||||
name='test_var_wei0Rei9ahzooSohK1ph',
|
||||
default_value='key_1_Queit2juchoocos2Vugh',
|
||||
input_type='choice',
|
||||
choices=(
|
||||
{'value': 'key_1_Queit2juchoocos2Vugh', 'display_name': 'label_1_Queit2juchoocos2Vugh'},
|
||||
{'value': 'key_2_yahb2ain1aeZ1lea1Pei', 'display_name': 'label_2_yahb2ain1aeZ1lea1Pei'}))
|
||||
|
||||
yield ConfigVariable(
|
||||
name='test_var_Hi7Oje8Oith7goopeeng',
|
||||
default_value='',
|
||||
validators=(validator_for_testing,))
|
||||
|
@ -1,6 +1,6 @@
|
||||
from django.test.client import Client
|
||||
|
||||
from openslides.config.api import config
|
||||
from openslides.core.config import config
|
||||
from openslides.motions.models import Motion
|
||||
from openslides.utils.test import TestCase
|
||||
|
||||
|
@ -3,7 +3,7 @@ from django.core.urlresolvers import reverse
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APIClient
|
||||
|
||||
from openslides.config.api import config
|
||||
from openslides.core.config import config
|
||||
from openslides.core.models import Tag
|
||||
from openslides.motions.models import Category, Motion
|
||||
from openslides.utils.test import TestCase
|
||||
|
@ -1,8 +1,8 @@
|
||||
from django.dispatch import receiver
|
||||
|
||||
from openslides.config.api import ConfigVariable, config
|
||||
from openslides.config.exceptions import ConfigError, ConfigNotFound
|
||||
from openslides.config.signals import config_signal
|
||||
from openslides.core.config import ConfigVariable, config
|
||||
from openslides.core.exceptions import ConfigError, ConfigNotFound
|
||||
from openslides.core.signals import config_signal
|
||||
from openslides.utils.test import TestCase
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
from unittest import skip
|
||||
|
||||
from openslides.config.api import config
|
||||
from openslides.core.config import config
|
||||
from openslides.motions.exceptions import WorkflowError
|
||||
from openslides.motions.models import Motion, State, Workflow
|
||||
from openslides.users.models import User
|
||||
|
@ -2,7 +2,7 @@ import os
|
||||
import sys
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from openslides.config.api import config
|
||||
from openslides.core.config import config
|
||||
from openslides.utils import main
|
||||
from openslides.utils.test import TestCase
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
from unittest import TestCase
|
||||
from unittest.mock import patch
|
||||
|
||||
from openslides.config.api import ConfigVariable
|
||||
from openslides.core.config import ConfigVariable
|
||||
|
||||
|
||||
class TestConfigVariable(TestCase):
|
||||
@patch('openslides.config.api.config', {'test_variable': None})
|
||||
@patch('openslides.core.config.config', {'test_variable': None})
|
||||
def test_default_value_in_data(self):
|
||||
"""
|
||||
Tests, that the default_value attribute is in the 'data' property of
|
||||
|
Loading…
Reference in New Issue
Block a user