Merge pull request #1123 from ostcar/overlay_error
dont throw errors in overlay.get_projector_html
This commit is contained in:
commit
e1e5ffd14c
@ -112,10 +112,7 @@ class Item(SlideMixin, MPTTModel):
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super(Item, self).save(*args, **kwargs)
|
||||
active_slide = get_active_slide()
|
||||
active_slide_pk = active_slide.get('pk', None)
|
||||
if (active_slide['callback'] == 'agenda' and
|
||||
unicode(self.parent_id) == unicode(active_slide_pk)):
|
||||
if self.parent and self.parent.is_active_slide():
|
||||
update_projector()
|
||||
|
||||
def __unicode__(self):
|
||||
@ -359,14 +356,10 @@ class Speaker(models.Model):
|
||||
Checks, if the agenda item, or parts of it, is on the projector.
|
||||
If yes, it updates the projector.
|
||||
"""
|
||||
active_slide = get_active_slide()
|
||||
active_slide_pk = active_slide.get('pk', None)
|
||||
slide_type = active_slide.get('type', None)
|
||||
if (active_slide['callback'] == 'agenda' and
|
||||
unicode(self.item_id) == unicode(active_slide_pk)):
|
||||
if slide_type == 'list_of_speakers':
|
||||
if self.item.is_active_slide():
|
||||
if get_active_slide().get('type', None) == 'list_of_speakers':
|
||||
update_projector()
|
||||
elif slide_type is None:
|
||||
else:
|
||||
update_projector_overlay('agenda_speaker')
|
||||
|
||||
def begin_speach(self):
|
||||
|
@ -13,7 +13,7 @@ from django.utils.translation import ugettext_lazy, ugettext_noop
|
||||
|
||||
from openslides.config.api import config, ConfigPage, ConfigVariable
|
||||
from openslides.config.signals import config_signal
|
||||
from openslides.projector.api import get_active_slide
|
||||
from openslides.projector.api import get_active_slide, get_active_object
|
||||
from openslides.projector.projector import Overlay
|
||||
from openslides.projector.signals import projector_overlays
|
||||
|
||||
@ -97,23 +97,30 @@ def agenda_list_of_speakers(sender, **kwargs):
|
||||
The overlay is only shown on agenda-items and not on the
|
||||
list-of-speakers slide.
|
||||
"""
|
||||
active_slide = get_active_slide()
|
||||
slide_type = active_slide.get('type', None)
|
||||
active_slide_pk = active_slide.get('pk', None)
|
||||
if (active_slide['callback'] == 'agenda' and
|
||||
slide_type != 'list_of_speakers' and
|
||||
active_slide_pk is not None):
|
||||
item = Item.objects.get(pk=active_slide_pk)
|
||||
slide = get_active_object()
|
||||
if isinstance(slide, Item):
|
||||
item = slide
|
||||
else:
|
||||
# TODO: If there are more the one items, use the first one in the
|
||||
# mptt tree that is not closed
|
||||
try:
|
||||
item = Item.objects.filter(
|
||||
content_type=ContentType.objects.get_for_model(slide),
|
||||
object_id=slide.pk)[0]
|
||||
except IndexError:
|
||||
item = None
|
||||
|
||||
if item and get_active_slide().get('type', None) != 'list_of_speakers':
|
||||
list_of_speakers = item.get_list_of_speakers(
|
||||
old_speakers_count=config['agenda_show_last_speakers'],
|
||||
coming_speakers_count=5)
|
||||
context = {
|
||||
|
||||
value = render_to_string('agenda/overlay_speaker_projector.html', {
|
||||
'list_of_speakers': list_of_speakers,
|
||||
'closed': item.speaker_list_closed,
|
||||
}
|
||||
return render_to_string('agenda/overlay_speaker_projector.html', context)
|
||||
'closed': item.speaker_list_closed})
|
||||
else:
|
||||
return None
|
||||
value = None
|
||||
return value
|
||||
|
||||
return Overlay(name, get_widget_html, get_projector_html)
|
||||
|
||||
|
@ -60,4 +60,4 @@ def agenda_slide(**kwargs):
|
||||
return slide
|
||||
|
||||
|
||||
register_slide('agenda', agenda_slide)
|
||||
register_slide('agenda', agenda_slide, Item)
|
||||
|
@ -30,4 +30,4 @@ def mediafile_presentation_as_slide(**kwargs):
|
||||
return render_to_string('mediafile/presentation_slide.html', context)
|
||||
|
||||
|
||||
register_slide('mediafile', mediafile_presentation_as_slide)
|
||||
register_slide('mediafile', mediafile_presentation_as_slide, Mediafile)
|
||||
|
@ -20,6 +20,14 @@ A dictonary where the key is the name of a slide, and the value is a
|
||||
callable object which returns the html code for a slide.
|
||||
"""
|
||||
|
||||
slide_model = {}
|
||||
"""
|
||||
A dictonary for SlideMixin models to reference from the slide_callback_name to
|
||||
the Model
|
||||
"""
|
||||
# TODO: Find a bether way to do this. Maybe by reimplementing slides with
|
||||
# metaclasses
|
||||
|
||||
|
||||
class SlideError(OpenSlidesError):
|
||||
pass
|
||||
@ -139,11 +147,15 @@ def get_projector_overlays_js(as_json=False):
|
||||
return javascript
|
||||
|
||||
|
||||
def register_slide(name, callback):
|
||||
def register_slide(name, callback, model=None):
|
||||
"""
|
||||
Register a function as slide callback.
|
||||
Registers a function as slide callback.
|
||||
|
||||
The optional argument 'model' is used to register a SlideModelClass.
|
||||
"""
|
||||
slide_callback[name] = callback
|
||||
if model is not None:
|
||||
slide_model[name] = model
|
||||
|
||||
|
||||
def register_slide_model(SlideModel, template):
|
||||
@ -169,7 +181,7 @@ def register_slide_model(SlideModel, template):
|
||||
|
||||
return render_to_string(template, context)
|
||||
|
||||
register_slide(SlideModel.slide_callback_name, model_slide)
|
||||
register_slide(SlideModel.slide_callback_name, model_slide, SlideModel)
|
||||
|
||||
|
||||
def set_active_slide(callback, **kwargs):
|
||||
@ -192,6 +204,26 @@ def get_active_slide():
|
||||
return config['projector_active_slide']
|
||||
|
||||
|
||||
def get_active_object():
|
||||
"""
|
||||
Returns an object if the active slide is an instance of SlideMixin.
|
||||
In other case, returns None
|
||||
"""
|
||||
active_slide_dict = get_active_slide()
|
||||
callback_name = active_slide_dict.get('callback', None)
|
||||
object_pk = active_slide_dict.get('pk', None)
|
||||
try:
|
||||
Model = slide_model[callback_name]
|
||||
except KeyError:
|
||||
value = None
|
||||
else:
|
||||
try:
|
||||
value = Model.objects.get(pk=object_pk)
|
||||
except Model.DoesNotExist:
|
||||
value = None
|
||||
return value
|
||||
|
||||
|
||||
def get_all_widgets(request, session=False):
|
||||
"""
|
||||
Collects the widgets from all apps and returns the Widget objects as sorted
|
||||
|
@ -1,5 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.conf import settings
|
||||
from django.template import RequestContext
|
||||
from django.template.loader import render_to_string
|
||||
|
||||
@ -86,7 +87,15 @@ class Overlay(object):
|
||||
"""
|
||||
Returns the html code for the projector.
|
||||
"""
|
||||
return self.get_html_wrapper(self.projector_html_callback())
|
||||
try:
|
||||
value = self.get_html_wrapper(self.projector_html_callback())
|
||||
except Exception as exception:
|
||||
if settings.DEBUG:
|
||||
raise exception
|
||||
else:
|
||||
# Catch all errors, so an overlay can not kill the projector
|
||||
value = ''
|
||||
return value
|
||||
|
||||
def get_javascript(self):
|
||||
"""
|
||||
|
@ -139,9 +139,14 @@ class ApiFunctions(TestCase):
|
||||
|
||||
def test_register_slide(self):
|
||||
mock_slide_callback = {}
|
||||
mock_slide_model = {}
|
||||
with patch('openslides.projector.api.slide_model', mock_slide_model):
|
||||
with patch('openslides.projector.api.slide_callback', mock_slide_callback):
|
||||
projector_api.register_slide('some name', 'some callback')
|
||||
self.assertEqual(mock_slide_callback, {'some name': 'some callback'})
|
||||
projector_api.register_slide('other name', 'other callback', 'Model')
|
||||
self.assertEqual(mock_slide_callback, {'some name': 'some callback',
|
||||
'other name': 'other callback'})
|
||||
self.assertEqual(mock_slide_model, {'other name': 'Model'})
|
||||
|
||||
@patch('openslides.projector.api.render_to_string')
|
||||
@patch('openslides.projector.api.register_slide')
|
||||
@ -156,6 +161,7 @@ class ApiFunctions(TestCase):
|
||||
projector_api.register_slide_model(mock_SlideModel, 'some template')
|
||||
used_args, __ = mock_register_slide.call_args
|
||||
self.assertEqual(used_args[0], 'mock_callback_name')
|
||||
self.assertEqual(used_args[2], mock_SlideModel)
|
||||
|
||||
# Test the generated slide function
|
||||
used_args[1](pk=1)
|
||||
@ -182,3 +188,26 @@ class ApiFunctions(TestCase):
|
||||
with patch('openslides.projector.api.config', mock_config):
|
||||
value = projector_api.get_active_slide()
|
||||
self.assertEqual(value, 'value')
|
||||
|
||||
def test_get_active_object(self):
|
||||
mock_Model = MagicMock()
|
||||
mock_Model.DoesNotExist = Exception
|
||||
mock_slide_model = {'mock_model': mock_Model}
|
||||
mock_active_slide = {'callback': 'unknown'}
|
||||
mock_get_active_slide = MagicMock(return_value=mock_active_slide)
|
||||
|
||||
with patch('openslides.projector.api.get_active_slide', mock_get_active_slide):
|
||||
with patch('openslides.projector.api.slide_model', mock_slide_model):
|
||||
# test unknwon slide_callback_name
|
||||
self.assertIsNone(projector_api.get_active_object())
|
||||
|
||||
# test unknown object
|
||||
mock_Model.objects.get.side_effect = Exception
|
||||
mock_active_slide.update(callback='mock_model', pk=42)
|
||||
self.assertIsNone(projector_api.get_active_object())
|
||||
mock_Model.objects.get.assert_called_with(pk=42)
|
||||
|
||||
# test success
|
||||
mock_Model.objects.get.side_effect = None
|
||||
mock_Model.objects.get.return_value = 'success'
|
||||
self.assertEqual(projector_api.get_active_object(), 'success')
|
||||
|
26
tests/projector/test_overlays.py
Normal file
26
tests/projector/test_overlays.py
Normal file
@ -0,0 +1,26 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from mock import MagicMock, patch
|
||||
|
||||
from openslides.projector.projector import Overlay
|
||||
from openslides.utils.test import TestCase
|
||||
|
||||
|
||||
class OverlayTest(TestCase):
|
||||
def test_error_in_html(self):
|
||||
"""
|
||||
Tests that the methof get_projector_html does not raise any errors.
|
||||
"""
|
||||
get_projector_html = MagicMock(side_effect=Exception('no good error'))
|
||||
overlay = Overlay('test_overlay', lambda: 'widget_html', get_projector_html)
|
||||
|
||||
# Test in productive mode
|
||||
with patch('openslides.projector.projector.settings.DEBUG', False):
|
||||
self.assertEqual(overlay.get_projector_html(), '')
|
||||
|
||||
# Test in debug mode
|
||||
with patch('openslides.projector.projector.settings.DEBUG', True):
|
||||
self.assertRaisesMessage(
|
||||
Exception,
|
||||
'no good error',
|
||||
overlay.get_projector_html)
|
Loading…
Reference in New Issue
Block a user