Merge pull request #3382 from ostcar/remove_dispatch
Rewrite projector_element without dispatch
This commit is contained in:
commit
71e154ec6d
@ -1,6 +1,7 @@
|
|||||||
from django.apps import AppConfig
|
from django.apps import AppConfig
|
||||||
|
|
||||||
from ..utils.collection import Collection
|
from ..utils.collection import Collection
|
||||||
|
from ..utils.projector import register_projector_elements
|
||||||
|
|
||||||
|
|
||||||
class AgendaAppConfig(AppConfig):
|
class AgendaAppConfig(AppConfig):
|
||||||
@ -10,16 +11,13 @@ class AgendaAppConfig(AppConfig):
|
|||||||
angular_projector_module = True
|
angular_projector_module = True
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
# Load projector elements.
|
|
||||||
# Do this by just importing all from these files.
|
|
||||||
from . import projector # noqa
|
|
||||||
|
|
||||||
# Import all required stuff.
|
# Import all required stuff.
|
||||||
from django.db.models.signals import pre_delete, post_save
|
from django.db.models.signals import pre_delete, post_save
|
||||||
from openslides.core.config import config
|
from ..core.config import config
|
||||||
from openslides.core.signals import permission_change, user_data_required
|
from ..core.signals import permission_change, user_data_required
|
||||||
from openslides.utils.rest_api import router
|
from ..utils.rest_api import router
|
||||||
from .config_variables import get_config_variables
|
from .config_variables import get_config_variables
|
||||||
|
from .projector import get_projector_elements
|
||||||
from .signals import (
|
from .signals import (
|
||||||
get_permission_change_data,
|
get_permission_change_data,
|
||||||
listen_to_related_object_post_delete,
|
listen_to_related_object_post_delete,
|
||||||
@ -27,8 +25,9 @@ class AgendaAppConfig(AppConfig):
|
|||||||
required_users)
|
required_users)
|
||||||
from .views import ItemViewSet
|
from .views import ItemViewSet
|
||||||
|
|
||||||
# Define config variables
|
# Define config variables and projector elements.
|
||||||
config.update_config_variables(get_config_variables())
|
config.update_config_variables(get_config_variables())
|
||||||
|
register_projector_elements(get_projector_elements())
|
||||||
|
|
||||||
# Connect signals.
|
# Connect signals.
|
||||||
post_save.connect(
|
post_save.connect(
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
from typing import Generator, Type
|
||||||
|
|
||||||
from ..core.config import config
|
from ..core.config import config
|
||||||
from ..core.exceptions import ProjectorException
|
from ..core.exceptions import ProjectorException
|
||||||
from ..core.models import Projector
|
from ..core.models import Projector
|
||||||
@ -136,3 +138,9 @@ class CurrentListOfSpeakersSlide(ProjectorElement):
|
|||||||
output.extend(self.get_requirements_as_collection_elements(config_entry))
|
output.extend(self.get_requirements_as_collection_elements(config_entry))
|
||||||
break
|
break
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
|
||||||
|
def get_projector_elements() -> Generator[Type[ProjectorElement], None, None]:
|
||||||
|
yield ItemListSlide
|
||||||
|
yield ListOfSpeakersSlide
|
||||||
|
yield CurrentListOfSpeakersSlide
|
||||||
|
@ -4,6 +4,7 @@ from django.apps import AppConfig
|
|||||||
from mypy_extensions import TypedDict
|
from mypy_extensions import TypedDict
|
||||||
|
|
||||||
from ..utils.collection import Collection
|
from ..utils.collection import Collection
|
||||||
|
from ..utils.projector import register_projector_elements
|
||||||
|
|
||||||
|
|
||||||
class AssignmentsAppConfig(AppConfig):
|
class AssignmentsAppConfig(AppConfig):
|
||||||
@ -13,20 +14,18 @@ class AssignmentsAppConfig(AppConfig):
|
|||||||
angular_projector_module = True
|
angular_projector_module = True
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
# Load projector elements.
|
|
||||||
# Do this by just importing all from these files.
|
|
||||||
from . import projector # noqa
|
|
||||||
|
|
||||||
# Import all required stuff.
|
# Import all required stuff.
|
||||||
from openslides.core.config import config
|
from ..core.config import config
|
||||||
from openslides.core.signals import permission_change, user_data_required
|
from ..core.signals import permission_change, user_data_required
|
||||||
from openslides.utils.rest_api import router
|
from ..utils.rest_api import router
|
||||||
from .config_variables import get_config_variables
|
from .config_variables import get_config_variables
|
||||||
|
from .projector import get_projector_elements
|
||||||
from .signals import get_permission_change_data, required_users
|
from .signals import get_permission_change_data, required_users
|
||||||
from .views import AssignmentViewSet, AssignmentPollViewSet
|
from .views import AssignmentViewSet, AssignmentPollViewSet
|
||||||
|
|
||||||
# Define config variables
|
# Define config variables and projector elements.
|
||||||
config.update_config_variables(get_config_variables())
|
config.update_config_variables(get_config_variables())
|
||||||
|
register_projector_elements(get_projector_elements())
|
||||||
|
|
||||||
# Connect signals.
|
# Connect signals.
|
||||||
permission_change.connect(
|
permission_change.connect(
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
from typing import Generator, Type
|
||||||
|
|
||||||
from ..core.exceptions import ProjectorException
|
from ..core.exceptions import ProjectorException
|
||||||
from ..utils.projector import ProjectorElement
|
from ..utils.projector import ProjectorElement
|
||||||
from .models import Assignment, AssignmentPoll
|
from .models import Assignment, AssignmentPoll
|
||||||
@ -64,3 +66,7 @@ class AssignmentSlide(ProjectorElement):
|
|||||||
else:
|
else:
|
||||||
data = {'agenda_item_id': assignment.agenda_item_id}
|
data = {'agenda_item_id': assignment.agenda_item_id}
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def get_projector_elements() -> Generator[Type[ProjectorElement], None, None]:
|
||||||
|
yield AssignmentSlide
|
||||||
|
@ -3,6 +3,7 @@ from django.conf import settings
|
|||||||
from django.db.models.signals import post_migrate
|
from django.db.models.signals import post_migrate
|
||||||
|
|
||||||
from ..utils.collection import Collection
|
from ..utils.collection import Collection
|
||||||
|
from ..utils.projector import register_projector_elements
|
||||||
|
|
||||||
|
|
||||||
class CoreAppConfig(AppConfig):
|
class CoreAppConfig(AppConfig):
|
||||||
@ -12,15 +13,12 @@ class CoreAppConfig(AppConfig):
|
|||||||
angular_projector_module = True
|
angular_projector_module = True
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
# Load projector elements.
|
|
||||||
# Do this by just importing all from these files.
|
|
||||||
from . import projector # noqa
|
|
||||||
|
|
||||||
# Import all required stuff.
|
# Import all required stuff.
|
||||||
from .config import config
|
from .config import config
|
||||||
from .signals import post_permission_creation
|
from .signals import post_permission_creation
|
||||||
from ..utils.rest_api import router
|
from ..utils.rest_api import router
|
||||||
from .config_variables import get_config_variables
|
from .config_variables import get_config_variables
|
||||||
|
from .projector import get_projector_elements
|
||||||
from .signals import (
|
from .signals import (
|
||||||
delete_django_app_permissions,
|
delete_django_app_permissions,
|
||||||
get_permission_change_data,
|
get_permission_change_data,
|
||||||
@ -36,8 +34,9 @@ class CoreAppConfig(AppConfig):
|
|||||||
TagViewSet,
|
TagViewSet,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Define config variables
|
# Define config variables and projector elements.
|
||||||
config.update_config_variables(get_config_variables())
|
config.update_config_variables(get_config_variables())
|
||||||
|
register_projector_elements(get_projector_elements())
|
||||||
|
|
||||||
# Connect signals.
|
# Connect signals.
|
||||||
post_permission_creation.connect(
|
post_permission_creation.connect(
|
||||||
|
@ -5,7 +5,7 @@ from jsonfield import JSONField
|
|||||||
|
|
||||||
from ..utils.collection import CollectionElement
|
from ..utils.collection import CollectionElement
|
||||||
from ..utils.models import RESTModelMixin
|
from ..utils.models import RESTModelMixin
|
||||||
from ..utils.projector import ProjectorElement
|
from ..utils.projector import get_all_projector_elements
|
||||||
from .access_permissions import (
|
from .access_permissions import (
|
||||||
ChatMessageAccessPermissions,
|
ChatMessageAccessPermissions,
|
||||||
ConfigAccessPermissions,
|
ConfigAccessPermissions,
|
||||||
@ -110,9 +110,7 @@ class Projector(RESTModelMixin, models.Model):
|
|||||||
result is also used.
|
result is also used.
|
||||||
"""
|
"""
|
||||||
# Get all elements from all apps.
|
# Get all elements from all apps.
|
||||||
elements = {}
|
elements = get_all_projector_elements()
|
||||||
for element in ProjectorElement.get_all(): # type: ignore
|
|
||||||
elements[element.name] = element
|
|
||||||
|
|
||||||
# Parse result
|
# Parse result
|
||||||
result = {}
|
result = {}
|
||||||
@ -137,9 +135,7 @@ class Projector(RESTModelMixin, models.Model):
|
|||||||
Generator which returns all instances that are shown on this projector.
|
Generator which returns all instances that are shown on this projector.
|
||||||
"""
|
"""
|
||||||
# Get all elements from all apps.
|
# Get all elements from all apps.
|
||||||
elements = {}
|
elements = get_all_projector_elements()
|
||||||
for element in ProjectorElement.get_all(): # type: ignore
|
|
||||||
elements[element.name] = element
|
|
||||||
|
|
||||||
# Generator
|
# Generator
|
||||||
for key, value in self.config.items():
|
for key, value in self.config.items():
|
||||||
@ -166,11 +162,8 @@ class Projector(RESTModelMixin, models.Model):
|
|||||||
# It is necessary to parse all active projector elements to check whether they require some data.
|
# It is necessary to parse all active projector elements to check whether they require some data.
|
||||||
this_projector = collection_element.collection_string == self.get_collection_string() and collection_element.id == self.pk
|
this_projector = collection_element.collection_string == self.get_collection_string() and collection_element.id == self.pk
|
||||||
collection_element.information['this_projector'] = this_projector
|
collection_element.information['this_projector'] = this_projector
|
||||||
elements = {}
|
|
||||||
|
|
||||||
# Build projector elements.
|
elements = get_all_projector_elements()
|
||||||
for element in ProjectorElement.get_all(): # type: ignore
|
|
||||||
elements[element.name] = element
|
|
||||||
|
|
||||||
# Iterate over all active projector elements.
|
# Iterate over all active projector elements.
|
||||||
for key, value in self.config.items():
|
for key, value in self.config.items():
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
from typing import Generator, Type
|
||||||
|
|
||||||
from ..utils.projector import ProjectorElement
|
from ..utils.projector import ProjectorElement
|
||||||
from .exceptions import ProjectorException
|
from .exceptions import ProjectorException
|
||||||
from .models import Countdown, ProjectorMessage
|
from .models import Countdown, ProjectorMessage
|
||||||
@ -48,3 +50,9 @@ class ProjectorMessageElement(ProjectorElement):
|
|||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
yield message
|
yield message
|
||||||
|
|
||||||
|
|
||||||
|
def get_projector_elements() -> Generator[Type[ProjectorElement], None, None]:
|
||||||
|
yield Clock
|
||||||
|
yield CountdownElement
|
||||||
|
yield ProjectorMessageElement
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from django.apps import AppConfig
|
from django.apps import AppConfig
|
||||||
|
|
||||||
from ..utils.collection import Collection
|
from ..utils.collection import Collection
|
||||||
|
from ..utils.projector import register_projector_elements
|
||||||
|
|
||||||
|
|
||||||
class MediafilesAppConfig(AppConfig):
|
class MediafilesAppConfig(AppConfig):
|
||||||
@ -10,16 +11,16 @@ class MediafilesAppConfig(AppConfig):
|
|||||||
angular_projector_module = True
|
angular_projector_module = True
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
# Load projector elements.
|
|
||||||
# Do this by just importing all from these files.
|
|
||||||
from . import projector # noqa
|
|
||||||
|
|
||||||
# Import all required stuff.
|
# Import all required stuff.
|
||||||
from openslides.core.signals import permission_change, user_data_required
|
from openslides.core.signals import permission_change, user_data_required
|
||||||
from openslides.utils.rest_api import router
|
from openslides.utils.rest_api import router
|
||||||
|
from .projector import get_projector_elements
|
||||||
from .signals import get_permission_change_data, required_users
|
from .signals import get_permission_change_data, required_users
|
||||||
from .views import MediafileViewSet
|
from .views import MediafileViewSet
|
||||||
|
|
||||||
|
# Define projector elements.
|
||||||
|
register_projector_elements(get_projector_elements())
|
||||||
|
|
||||||
# Connect signals.
|
# Connect signals.
|
||||||
permission_change.connect(
|
permission_change.connect(
|
||||||
get_permission_change_data,
|
get_permission_change_data,
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
from typing import Generator, Type
|
||||||
|
|
||||||
from ..core.exceptions import ProjectorException
|
from ..core.exceptions import ProjectorException
|
||||||
from ..utils.projector import ProjectorElement
|
from ..utils.projector import ProjectorElement
|
||||||
from .models import Mediafile
|
from .models import Mediafile
|
||||||
@ -21,3 +23,7 @@ class MediafileSlide(ProjectorElement):
|
|||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
yield mediafile
|
yield mediafile
|
||||||
|
|
||||||
|
|
||||||
|
def get_projector_elements() -> Generator[Type[ProjectorElement], None, None]:
|
||||||
|
yield MediafileSlide
|
||||||
|
@ -2,6 +2,7 @@ from django.apps import AppConfig
|
|||||||
from django.db.models.signals import post_migrate
|
from django.db.models.signals import post_migrate
|
||||||
|
|
||||||
from ..utils.collection import Collection
|
from ..utils.collection import Collection
|
||||||
|
from ..utils.projector import register_projector_elements
|
||||||
|
|
||||||
|
|
||||||
class MotionsAppConfig(AppConfig):
|
class MotionsAppConfig(AppConfig):
|
||||||
@ -11,20 +12,18 @@ class MotionsAppConfig(AppConfig):
|
|||||||
angular_projector_module = True
|
angular_projector_module = True
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
# Load projector elements.
|
|
||||||
# Do this by just importing all from these files.
|
|
||||||
from . import projector # noqa
|
|
||||||
|
|
||||||
# Import all required stuff.
|
# Import all required stuff.
|
||||||
from openslides.core.config import config
|
from openslides.core.config import config
|
||||||
from openslides.core.signals import permission_change, user_data_required
|
from openslides.core.signals import permission_change, user_data_required
|
||||||
from openslides.utils.rest_api import router
|
from openslides.utils.rest_api import router
|
||||||
from .config_variables import get_config_variables
|
from .config_variables import get_config_variables
|
||||||
|
from .projector import get_projector_elements
|
||||||
from .signals import create_builtin_workflows, get_permission_change_data, required_users
|
from .signals import create_builtin_workflows, get_permission_change_data, required_users
|
||||||
from .views import CategoryViewSet, MotionViewSet, MotionBlockViewSet, MotionPollViewSet, MotionChangeRecommendationViewSet, WorkflowViewSet
|
from .views import CategoryViewSet, MotionViewSet, MotionBlockViewSet, MotionPollViewSet, MotionChangeRecommendationViewSet, WorkflowViewSet
|
||||||
|
|
||||||
# Define config variables
|
# Define config variables and projector elements.
|
||||||
config.update_config_variables(get_config_variables())
|
config.update_config_variables(get_config_variables())
|
||||||
|
register_projector_elements(get_projector_elements())
|
||||||
|
|
||||||
# Connect signals.
|
# Connect signals.
|
||||||
post_migrate.connect(create_builtin_workflows, dispatch_uid='motion_create_builtin_workflows')
|
post_migrate.connect(create_builtin_workflows, dispatch_uid='motion_create_builtin_workflows')
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
from typing import Generator, Type
|
||||||
|
|
||||||
from ..core.exceptions import ProjectorException
|
from ..core.exceptions import ProjectorException
|
||||||
from ..utils.projector import ProjectorElement
|
from ..utils.projector import ProjectorElement
|
||||||
from .models import Motion, MotionBlock, MotionChangeRecommendation, Workflow
|
from .models import Motion, MotionBlock, MotionChangeRecommendation, Workflow
|
||||||
@ -90,3 +92,8 @@ class MotionBlockSlide(ProjectorElement):
|
|||||||
else:
|
else:
|
||||||
data = {'agenda_item_id': motion_block.agenda_item_id}
|
data = {'agenda_item_id': motion_block.agenda_item_id}
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def get_projector_elements() -> Generator[Type[ProjectorElement], None, None]:
|
||||||
|
yield MotionSlide
|
||||||
|
yield MotionBlockSlide
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from django.apps import AppConfig
|
from django.apps import AppConfig
|
||||||
|
|
||||||
from ..utils.collection import Collection
|
from ..utils.collection import Collection
|
||||||
|
from ..utils.projector import register_projector_elements
|
||||||
|
|
||||||
|
|
||||||
class TopicsAppConfig(AppConfig):
|
class TopicsAppConfig(AppConfig):
|
||||||
@ -10,16 +11,16 @@ class TopicsAppConfig(AppConfig):
|
|||||||
angular_projector_module = True
|
angular_projector_module = True
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
# Load projector elements.
|
|
||||||
# Do this by just importing all from these files.
|
|
||||||
from . import projector # noqa
|
|
||||||
|
|
||||||
# Import all required stuff.
|
# Import all required stuff.
|
||||||
from openslides.core.signals import permission_change
|
from openslides.core.signals import permission_change
|
||||||
from ..utils.rest_api import router
|
from ..utils.rest_api import router
|
||||||
|
from .projector import get_projector_elements
|
||||||
from .signals import get_permission_change_data
|
from .signals import get_permission_change_data
|
||||||
from .views import TopicViewSet
|
from .views import TopicViewSet
|
||||||
|
|
||||||
|
# Define projector elements.
|
||||||
|
register_projector_elements(get_projector_elements())
|
||||||
|
|
||||||
# Connect signals.
|
# Connect signals.
|
||||||
permission_change.connect(
|
permission_change.connect(
|
||||||
get_permission_change_data,
|
get_permission_change_data,
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
from typing import Generator, Type
|
||||||
|
|
||||||
from ..core.exceptions import ProjectorException
|
from ..core.exceptions import ProjectorException
|
||||||
from ..utils.projector import ProjectorElement
|
from ..utils.projector import ProjectorElement
|
||||||
from .models import Topic
|
from .models import Topic
|
||||||
@ -33,3 +35,7 @@ class TopicSlide(ProjectorElement):
|
|||||||
else:
|
else:
|
||||||
data = {'agenda_item_id': topic.agenda_item_id}
|
data = {'agenda_item_id': topic.agenda_item_id}
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def get_projector_elements() -> Generator[Type[ProjectorElement], None, None]:
|
||||||
|
yield TopicSlide
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from django.apps import AppConfig
|
from django.apps import AppConfig
|
||||||
|
|
||||||
from ..utils.collection import Collection
|
from ..utils.collection import Collection
|
||||||
|
from ..utils.projector import register_projector_elements
|
||||||
|
|
||||||
|
|
||||||
class UsersAppConfig(AppConfig):
|
class UsersAppConfig(AppConfig):
|
||||||
@ -10,20 +11,18 @@ class UsersAppConfig(AppConfig):
|
|||||||
angular_projector_module = True
|
angular_projector_module = True
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
# Load projector elements.
|
|
||||||
# Just import this file.
|
|
||||||
from . import projector # noqa
|
|
||||||
|
|
||||||
# Import all required stuff.
|
# Import all required stuff.
|
||||||
from ..core.config import config
|
from ..core.config import config
|
||||||
from ..core.signals import post_permission_creation, permission_change
|
from ..core.signals import post_permission_creation, permission_change
|
||||||
from ..utils.rest_api import router
|
from ..utils.rest_api import router
|
||||||
from .config_variables import get_config_variables
|
from .config_variables import get_config_variables
|
||||||
|
from .projector import get_projector_elements
|
||||||
from .signals import create_builtin_groups_and_admin, get_permission_change_data
|
from .signals import create_builtin_groups_and_admin, get_permission_change_data
|
||||||
from .views import GroupViewSet, PersonalNoteViewSet, UserViewSet
|
from .views import GroupViewSet, PersonalNoteViewSet, UserViewSet
|
||||||
|
|
||||||
# Define config variables
|
# Define config variables and projector elements.
|
||||||
config.update_config_variables(get_config_variables())
|
config.update_config_variables(get_config_variables())
|
||||||
|
register_projector_elements(get_projector_elements())
|
||||||
|
|
||||||
# Connect signals.
|
# Connect signals.
|
||||||
post_permission_creation.connect(
|
post_permission_creation.connect(
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
from typing import Generator, Type
|
||||||
|
|
||||||
from ..core.exceptions import ProjectorException
|
from ..core.exceptions import ProjectorException
|
||||||
from ..utils.projector import ProjectorElement
|
from ..utils.projector import ProjectorElement
|
||||||
from .models import User
|
from .models import User
|
||||||
@ -21,3 +23,7 @@ class UserSlide(ProjectorElement):
|
|||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
yield user
|
yield user
|
||||||
|
|
||||||
|
|
||||||
|
def get_projector_elements() -> Generator[Type[ProjectorElement], None, None]:
|
||||||
|
yield UserSlide
|
||||||
|
@ -1,112 +0,0 @@
|
|||||||
class SignalConnectMetaClass(type):
|
|
||||||
"""
|
|
||||||
Metaclass to connect the children of a base class to a Django signal.
|
|
||||||
|
|
||||||
Classes must have a signal argument and a get_dispatch_uid classmethod.
|
|
||||||
The signal argument must be the Django signal the class should be
|
|
||||||
connected to. The get_dispatch_uid classmethod must return a unique
|
|
||||||
value for each child class and None for base classes because they will
|
|
||||||
not be connected to the signal.
|
|
||||||
|
|
||||||
The classmethod get_all is added to every class using this metaclass.
|
|
||||||
Calling this on a base class or on child classes will retrieve all
|
|
||||||
connected children, one instance for each child class.
|
|
||||||
|
|
||||||
These instances will have a check_permission method which returns True
|
|
||||||
by default. You can override this method to return False on runtime if
|
|
||||||
you want to filter some children.
|
|
||||||
|
|
||||||
They will also have a get_default_weight method which returns the value
|
|
||||||
of the default_weight attribute which is 0 by default. You can override
|
|
||||||
the attribute or the method to sort the children.
|
|
||||||
|
|
||||||
Don't forget to set up the __init__ method so that it is able to receive
|
|
||||||
wildcard keyword arguments (see example below). This is necessary
|
|
||||||
because of Django's signal API.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
class Base(object, metaclass=SignalConnectMetaClass):
|
|
||||||
signal = django.dispatch.Signal()
|
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_dispatch_uid(cls):
|
|
||||||
if not cls.__name__ == 'Base':
|
|
||||||
return cls.__name__
|
|
||||||
|
|
||||||
class Child(Base):
|
|
||||||
pass
|
|
||||||
|
|
||||||
child = Base.get_all(request)[0]
|
|
||||||
assert Child == type(child)
|
|
||||||
"""
|
|
||||||
def __new__(metaclass, class_name, class_parents, class_attributes):
|
|
||||||
"""
|
|
||||||
Creates the class and connects it to the signal if so. Adds all
|
|
||||||
default attributes and methods.
|
|
||||||
"""
|
|
||||||
class_attributes['get_all'] = get_all
|
|
||||||
new_class = super().__new__(
|
|
||||||
metaclass, class_name, class_parents, class_attributes)
|
|
||||||
try:
|
|
||||||
dispatch_uid = new_class.get_dispatch_uid()
|
|
||||||
except AttributeError:
|
|
||||||
raise NotImplementedError('Your class %s must have a get_dispatch_uid classmethod.' % class_name)
|
|
||||||
if dispatch_uid is not None:
|
|
||||||
try:
|
|
||||||
signal = new_class.signal
|
|
||||||
except AttributeError:
|
|
||||||
raise NotImplementedError('Your class %s must have a signal argument, which must be a Django Signal instance.' % class_name)
|
|
||||||
else:
|
|
||||||
signal.connect(new_class, dispatch_uid=dispatch_uid)
|
|
||||||
attributes = {'check_permission': check_permission,
|
|
||||||
'get_default_weight': get_default_weight,
|
|
||||||
'default_weight': 0}
|
|
||||||
for name, attribute in attributes.items():
|
|
||||||
if not hasattr(new_class, name):
|
|
||||||
setattr(new_class, name, attribute)
|
|
||||||
return new_class
|
|
||||||
|
|
||||||
|
|
||||||
@classmethod # type: ignore
|
|
||||||
def get_all(cls, request=None):
|
|
||||||
"""
|
|
||||||
Collects all objects of the class created by the SignalConnectMetaClass
|
|
||||||
from all apps via signal. They are sorted using the get_default_weight
|
|
||||||
method. Does not return objects where check_permission returns False.
|
|
||||||
|
|
||||||
A django.http.HttpRequest object can optionally be given.
|
|
||||||
|
|
||||||
This classmethod is added as get_all classmethod to every class using
|
|
||||||
the SignalConnectMetaClass.
|
|
||||||
"""
|
|
||||||
kwargs = {'sender': cls}
|
|
||||||
if request is not None:
|
|
||||||
kwargs['request'] = request
|
|
||||||
all_objects = [obj for __, obj in cls.signal.send(**kwargs) if obj.check_permission()]
|
|
||||||
all_objects.sort(key=lambda obj: obj.get_default_weight())
|
|
||||||
return all_objects
|
|
||||||
|
|
||||||
|
|
||||||
def check_permission(self):
|
|
||||||
"""
|
|
||||||
Returns True by default. Override this to filter some children on runtime.
|
|
||||||
|
|
||||||
This method is added to every instance of classes using the
|
|
||||||
SignalConnectMetaClass.
|
|
||||||
"""
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def get_default_weight(self):
|
|
||||||
"""
|
|
||||||
Returns the value of the default_weight attribute by default. Override
|
|
||||||
this to sort some children on runtime.
|
|
||||||
|
|
||||||
This method is added to every instance of classes using the
|
|
||||||
SignalConnectMetaClass.
|
|
||||||
"""
|
|
||||||
return self.default_weight
|
|
@ -1,42 +1,17 @@
|
|||||||
from typing import Any, Dict, Iterable, List, Optional # noqa
|
from typing import Any, Dict, Generator, Iterable, List, Type
|
||||||
|
|
||||||
from django.dispatch import Signal
|
|
||||||
|
|
||||||
from .collection import CollectionElement
|
from .collection import CollectionElement
|
||||||
from .dispatch import SignalConnectMetaClass
|
|
||||||
|
|
||||||
|
|
||||||
class ProjectorElement(object, metaclass=SignalConnectMetaClass):
|
class ProjectorElement:
|
||||||
"""
|
"""
|
||||||
Base class for an element on the projector.
|
Base class for an element on the projector.
|
||||||
|
|
||||||
Every app which wants to add projector elements has to create classes
|
Every app which wants to add projector elements has to create classes
|
||||||
subclassing from this base class with different names. The name attribute
|
subclassing from this base class with different names. The name attribute
|
||||||
has to be set. The metaclass (SignalConnectMetaClass) does the rest of the
|
has to be set.
|
||||||
magic.
|
|
||||||
"""
|
"""
|
||||||
signal = Signal()
|
name = None # type: str
|
||||||
name = None # type: Optional[str]
|
|
||||||
|
|
||||||
def __init__(self, **kwargs: str) -> None:
|
|
||||||
"""
|
|
||||||
Initializes the projector element instance. This is done when the
|
|
||||||
signal is sent.
|
|
||||||
|
|
||||||
Because of Django's signal API, we have to take wildcard keyword
|
|
||||||
arguments. But they are not used here.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_dispatch_uid(cls) -> Optional[str]:
|
|
||||||
"""
|
|
||||||
Returns the classname as a unique string for each class. Returns None
|
|
||||||
for the base class so it will not be connected to the signal.
|
|
||||||
"""
|
|
||||||
if not cls.__name__ == 'ProjectorElement':
|
|
||||||
return cls.__name__
|
|
||||||
return None
|
|
||||||
|
|
||||||
def check_and_update_data(self, projector_object: Any, config_entry: Any) -> Any:
|
def check_and_update_data(self, projector_object: Any, config_entry: Any) -> Any:
|
||||||
"""
|
"""
|
||||||
@ -107,3 +82,25 @@ class ProjectorElement(object, metaclass=SignalConnectMetaClass):
|
|||||||
else:
|
else:
|
||||||
output = []
|
output = []
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
|
||||||
|
projector_elements = {} # type: Dict[str, ProjectorElement]
|
||||||
|
|
||||||
|
|
||||||
|
def register_projector_elements(elements: Generator[Type[ProjectorElement], None, None]) -> None:
|
||||||
|
"""
|
||||||
|
Registers projector elements for later use.
|
||||||
|
|
||||||
|
Has to be called in the app.ready method.
|
||||||
|
"""
|
||||||
|
for Element in elements:
|
||||||
|
element = Element()
|
||||||
|
projector_elements[element.name] = element
|
||||||
|
|
||||||
|
|
||||||
|
def get_all_projector_elements() -> Dict[str, ProjectorElement]:
|
||||||
|
"""
|
||||||
|
Returns all projector elements that where registered with
|
||||||
|
register_projector_elements()
|
||||||
|
"""
|
||||||
|
return projector_elements
|
||||||
|
@ -19,9 +19,6 @@ ignore_missing_imports = true
|
|||||||
strict_optional = true
|
strict_optional = true
|
||||||
check_untyped_defs = true
|
check_untyped_defs = true
|
||||||
|
|
||||||
[mypy-openslides.utils.dispatch]
|
|
||||||
ignore_errors = true
|
|
||||||
|
|
||||||
[mypy-openslides.utils.*]
|
[mypy-openslides.utils.*]
|
||||||
disallow_any = unannotated
|
disallow_any = unannotated
|
||||||
|
|
||||||
|
@ -4,6 +4,9 @@ from . import __description__, __verbose_name__
|
|||||||
|
|
||||||
|
|
||||||
class TestPluginAppConfig(AppConfig):
|
class TestPluginAppConfig(AppConfig):
|
||||||
|
"""
|
||||||
|
Test Plugin for the test tests.integration.core.test_views.VersionView
|
||||||
|
"""
|
||||||
name = 'tests.integration.test_plugin'
|
name = 'tests.integration.test_plugin'
|
||||||
label = 'tests.integration.test_plugin'
|
label = 'tests.integration.test_plugin'
|
||||||
verbose_name = __verbose_name__
|
verbose_name = __verbose_name__
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
from django.db import models
|
|
||||||
|
|
||||||
from openslides.projector.models import SlideMixin
|
|
||||||
|
|
||||||
|
|
||||||
class RelatedItem(SlideMixin, models.Model):
|
|
||||||
slide_callback_name = 'test_related_item'
|
|
||||||
name = models.CharField(max_length='255')
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
verbose_name = 'Related Item CHFNGEJ5634DJ34F'
|
|
||||||
|
|
||||||
def get_agenda_title(self):
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
def get_agenda_title_supplement(self):
|
|
||||||
return 'test item'
|
|
||||||
|
|
||||||
def get_absolute_url(self, link=None):
|
|
||||||
if link is None:
|
|
||||||
value = '/absolute-url-here/'
|
|
||||||
else:
|
|
||||||
value = super(RelatedItem, self).get_absolute_url(link)
|
|
||||||
return value
|
|
||||||
|
|
||||||
|
|
||||||
class BadRelatedItem(models.Model):
|
|
||||||
name = models.CharField(max_length='255')
|
|
@ -1,26 +0,0 @@
|
|||||||
from django.test.client import Client
|
|
||||||
|
|
||||||
from openslides.assignments.models import Assignment
|
|
||||||
from openslides.users.models import User
|
|
||||||
from openslides.utils.test import TestCase
|
|
||||||
|
|
||||||
|
|
||||||
class AssignmentPDFTest(TestCase):
|
|
||||||
"""
|
|
||||||
Tests for assignment PDF.
|
|
||||||
"""
|
|
||||||
def setUp(self):
|
|
||||||
# Admin
|
|
||||||
self.admin = User.objects.get(pk=1)
|
|
||||||
self.admin_client = Client()
|
|
||||||
self.admin_client.login(username='admin', password='admin')
|
|
||||||
|
|
||||||
def test_render_pdf(self):
|
|
||||||
Assignment.objects.create(title='assignment_name_ith8qua1Eiferoqu5ju2', description="test", open_posts=1)
|
|
||||||
response = self.admin_client.get('/assignments/print/')
|
|
||||||
self.assertEqual(response.status_code, 200)
|
|
||||||
|
|
||||||
def test_render_many_posts(self):
|
|
||||||
Assignment.objects.create(title='assignment_name_cohZ9shaipee3Phaing4', description="test", open_posts=20)
|
|
||||||
response = self.admin_client.get('/assignments/print/')
|
|
||||||
self.assertEqual(response.status_code, 200)
|
|
@ -1,263 +0,0 @@
|
|||||||
import os
|
|
||||||
import tempfile
|
|
||||||
from unittest import skip
|
|
||||||
|
|
||||||
from django.conf import settings
|
|
||||||
from django.contrib.auth.models import Permission
|
|
||||||
from django.contrib.contenttypes.models import ContentType
|
|
||||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
|
||||||
from django.test.client import Client
|
|
||||||
|
|
||||||
from openslides.mediafiles.models import Mediafile
|
|
||||||
from openslides.users.models import User
|
|
||||||
from openslides.utils.test import TestCase
|
|
||||||
|
|
||||||
|
|
||||||
class MediafileTest(TestCase):
|
|
||||||
"""
|
|
||||||
Unit test for the mediafile model.
|
|
||||||
"""
|
|
||||||
def setUp(self):
|
|
||||||
# Setup the three permissions
|
|
||||||
ct = ContentType.objects.get(app_label='mediafiles', model='mediafile')
|
|
||||||
perm_1 = Permission.objects.get(content_type=ct, codename='can_see')
|
|
||||||
perm_2 = Permission.objects.get(content_type=ct, codename='can_upload')
|
|
||||||
|
|
||||||
# Setup three different users
|
|
||||||
self.manager = User.objects.get(pk=1)
|
|
||||||
self.vip_user = User.objects.create_user('mediafile_test_vip_user', 'default')
|
|
||||||
self.vip_user.user_permissions.add(perm_1, perm_2)
|
|
||||||
self.normal_user = User.objects.create_user('mediafile_test_normal_user', 'default')
|
|
||||||
|
|
||||||
# Setup a mediafile object
|
|
||||||
self.tmp_dir = settings.MEDIA_ROOT
|
|
||||||
tmpfile_no, mediafile_path = tempfile.mkstemp(prefix='tmp_openslides_test_', dir=self.tmp_dir)
|
|
||||||
self.object = Mediafile.objects.create(title='Title File 1', mediafile=mediafile_path, uploader=self.normal_user)
|
|
||||||
os.close(tmpfile_no)
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
self.object.mediafile.delete(save=False)
|
|
||||||
super().tearDown()
|
|
||||||
|
|
||||||
def test_str(self):
|
|
||||||
self.assertEqual(str(self.object), 'Title File 1')
|
|
||||||
|
|
||||||
@skip
|
|
||||||
def test_absolute_url(self):
|
|
||||||
self.assertEqual(self.object.get_absolute_url(), '/mediafiles/1/edit/')
|
|
||||||
self.assertEqual(self.object.get_absolute_url('update'), '/mediafiles/1/edit/')
|
|
||||||
self.assertEqual(self.object.get_absolute_url(link='delete'), '/mediafiles/1/del/')
|
|
||||||
|
|
||||||
def login_clients(self):
|
|
||||||
"""
|
|
||||||
Helper function to login all three test users.
|
|
||||||
"""
|
|
||||||
client_manager = Client()
|
|
||||||
client_manager.login(username='admin', password='admin')
|
|
||||||
client_vip_user = Client()
|
|
||||||
client_vip_user.login(username='mediafile_test_vip_user', password='default')
|
|
||||||
client_normal_user = Client()
|
|
||||||
client_normal_user.login(username='mediafile_test_normal_user', password='default')
|
|
||||||
return {'client_manager': client_manager,
|
|
||||||
'client_vip_user': client_vip_user,
|
|
||||||
'client_normal_user': client_normal_user}
|
|
||||||
|
|
||||||
@skip
|
|
||||||
def test_see_mediafilelist(self):
|
|
||||||
for client in self.login_clients().values():
|
|
||||||
response = client.get('/mediafiles/')
|
|
||||||
self.assertEqual(response.status_code, 200)
|
|
||||||
self.assertTemplateUsed(response, 'mediafiles/mediafile_list.html')
|
|
||||||
|
|
||||||
@skip
|
|
||||||
def test_upload_mediafile_get_request(self):
|
|
||||||
clients = self.login_clients()
|
|
||||||
response = clients['client_manager'].get('/mediafiles/new/')
|
|
||||||
self.assertContains(response, '---------', status_code=200)
|
|
||||||
self.assertContains(response, '<option value="1" selected="selected">Administrator</option>', status_code=200)
|
|
||||||
self.assertTemplateUsed(response, 'mediafiles/mediafile_form.html')
|
|
||||||
|
|
||||||
response = clients['client_vip_user'].get('/mediafiles/new/')
|
|
||||||
self.assertNotContains(response, '<select id="id_uploader" name="uploader">', status_code=200)
|
|
||||||
self.assertTemplateUsed(response, 'mediafiles/mediafile_form.html')
|
|
||||||
|
|
||||||
response = clients['client_normal_user'].get('/mediafiles/new/')
|
|
||||||
self.assertEqual(response.status_code, 403)
|
|
||||||
|
|
||||||
@skip
|
|
||||||
def test_upload_mediafile_post_request(self):
|
|
||||||
# Test first user
|
|
||||||
client_1 = self.login_clients()['client_manager']
|
|
||||||
new_file_1 = SimpleUploadedFile(name='new_test_file.txt', content=bytes('test content hello manager', 'UTF-8'))
|
|
||||||
response_1 = client_1.post('/mediafiles/new/',
|
|
||||||
{'title': 'new_test_file_title_1',
|
|
||||||
'mediafile': new_file_1,
|
|
||||||
'uploader': self.normal_user.pk})
|
|
||||||
self.assertRedirects(response_1, expected_url='/mediafiles/', status_code=302, target_status_code=200)
|
|
||||||
object_1 = Mediafile.objects.latest('timestamp')
|
|
||||||
self.assertEqual(object_1.mediafile.url, '/media/file/new_test_file.txt')
|
|
||||||
self.assertEqual(object_1.uploader, self.normal_user)
|
|
||||||
path_1 = object_1.mediafile.path
|
|
||||||
object_1.mediafile.delete()
|
|
||||||
self.assertFalse(os.path.exists(path_1))
|
|
||||||
|
|
||||||
# Test second user
|
|
||||||
client_2 = self.login_clients()['client_vip_user']
|
|
||||||
new_file_2 = SimpleUploadedFile(name='new_test_file.txt', content=bytes('test content hello vip_user', 'UTF-8'))
|
|
||||||
response_2 = client_2.post('/mediafiles/new/',
|
|
||||||
{'title': 'new_test_file_title_2',
|
|
||||||
'mediafile': new_file_2})
|
|
||||||
self.assertEqual(response_2.status_code, 302)
|
|
||||||
# TODO: Check, why this does not work.
|
|
||||||
# self.assertRedirects(response_2, expected_url='/mediafiles/', status_code=302, target_status_code=200)
|
|
||||||
object_2 = Mediafile.objects.latest('timestamp')
|
|
||||||
self.assertEqual(object_2.mediafile.url, '/media/file/new_test_file.txt')
|
|
||||||
self.assertEqual(object_2.uploader, self.vip_user)
|
|
||||||
path_2 = object_2.mediafile.path
|
|
||||||
object_2.mediafile.delete()
|
|
||||||
self.assertFalse(os.path.exists(path_2))
|
|
||||||
|
|
||||||
# Test third user
|
|
||||||
client_3 = self.login_clients()['client_normal_user']
|
|
||||||
new_file_3 = SimpleUploadedFile(name='new_test_file.txt', content=bytes('test content hello vip_user', 'UTF-8'))
|
|
||||||
response_3 = client_3.post('/mediafiles/new/',
|
|
||||||
{'title': 'new_test_file_title_2',
|
|
||||||
'mediafile': new_file_3})
|
|
||||||
self.assertEqual(response_3.status_code, 403)
|
|
||||||
|
|
||||||
@skip
|
|
||||||
def test_edit_mediafile_get_request(self):
|
|
||||||
clients = self.login_clients()
|
|
||||||
response = clients['client_manager'].get('/mediafiles/1/edit/')
|
|
||||||
self.assertContains(response, '---------', status_code=200)
|
|
||||||
self.assertContains(response, '<option value="3" selected="selected">mediafile_test_normal_user</option>', status_code=200)
|
|
||||||
self.assertTemplateUsed(response, 'mediafiles/mediafile_form.html')
|
|
||||||
|
|
||||||
response = clients['client_vip_user'].get('/mediafiles/1/edit/')
|
|
||||||
self.assertEqual(response.status_code, 403)
|
|
||||||
|
|
||||||
response = clients['client_normal_user'].get('/mediafiles/1/edit/')
|
|
||||||
self.assertEqual(response.status_code, 403)
|
|
||||||
|
|
||||||
@skip
|
|
||||||
def test_edit_mediafile_get_request_own_file(self):
|
|
||||||
clients = self.login_clients()
|
|
||||||
self.object.uploader = self.vip_user
|
|
||||||
self.object.save()
|
|
||||||
response = clients['client_vip_user'].get('/mediafiles/1/edit/')
|
|
||||||
self.assertNotContains(response, '---------', status_code=200)
|
|
||||||
self.assertNotContains(response, '<option value="2" selected="selected">mediafile_test_vip_user</option>', status_code=200)
|
|
||||||
self.assertTemplateUsed(response, 'mediafiles/mediafile_form.html')
|
|
||||||
|
|
||||||
@skip
|
|
||||||
def test_edit_mediafile_post_request(self):
|
|
||||||
# Test only one user
|
|
||||||
tmpfile_no, mediafile_2_path = tempfile.mkstemp(prefix='tmp_openslides_test_', dir=self.tmp_dir)
|
|
||||||
os.close(tmpfile_no)
|
|
||||||
object_2 = Mediafile.objects.create(title='Title File 2', mediafile=mediafile_2_path, uploader=self.vip_user)
|
|
||||||
client_1 = self.login_clients()['client_manager']
|
|
||||||
new_file_1 = SimpleUploadedFile(name='new_test_file.txt', content=bytes('test content hello manager', 'UTF-8'))
|
|
||||||
response_1 = client_1.post('/mediafiles/2/edit/',
|
|
||||||
{'title': 'new_test_file_title_1',
|
|
||||||
'mediafile': new_file_1,
|
|
||||||
'uploader': self.manager.pk})
|
|
||||||
self.assertEqual(response_1.status_code, 302)
|
|
||||||
object_2 = Mediafile.objects.get(pk=2)
|
|
||||||
self.assertEqual(object_2.mediafile.url, '/media/file/new_test_file.txt')
|
|
||||||
self.assertEqual(object_2.uploader, self.manager)
|
|
||||||
path_2 = object_2.mediafile.path
|
|
||||||
object_2.mediafile.delete()
|
|
||||||
self.assertFalse(os.path.exists(path_2))
|
|
||||||
|
|
||||||
@skip
|
|
||||||
def test_edit_mediafile_post_request_own_file(self):
|
|
||||||
tmpfile_no, mediafile_2_path = tempfile.mkstemp(prefix='tmp_openslides_test_', dir=self.tmp_dir)
|
|
||||||
os.close(tmpfile_no)
|
|
||||||
object_2 = Mediafile.objects.create(title='Title File 2b', mediafile=mediafile_2_path, uploader=self.vip_user)
|
|
||||||
client = self.login_clients()['client_vip_user']
|
|
||||||
new_file_1 = SimpleUploadedFile(name='new_test_file.txt', content=bytes('test content hello vip user', 'UTF-8'))
|
|
||||||
response_1 = client.post('/mediafiles/2/edit/',
|
|
||||||
{'title': 'new_test_file_title_2b',
|
|
||||||
'mediafile': new_file_1})
|
|
||||||
self.assertEqual(response_1.status_code, 302)
|
|
||||||
object_2 = Mediafile.objects.get(pk=2)
|
|
||||||
self.assertEqual(object_2.mediafile.url, '/media/file/new_test_file.txt')
|
|
||||||
self.assertEqual(object_2.uploader, self.vip_user)
|
|
||||||
path_2 = object_2.mediafile.path
|
|
||||||
object_2.mediafile.delete()
|
|
||||||
self.assertFalse(os.path.exists(path_2))
|
|
||||||
|
|
||||||
@skip
|
|
||||||
def test_edit_mediafile_post_request_another_file(self):
|
|
||||||
client = self.login_clients()['client_vip_user']
|
|
||||||
new_file_1 = SimpleUploadedFile(name='new_test_file.txt', content=bytes('test content hello vip user', 'UTF-8'))
|
|
||||||
response = client.post('/mediafiles/1/edit/',
|
|
||||||
{'title': 'new_test_file_title_2c',
|
|
||||||
'mediafile': new_file_1})
|
|
||||||
self.assertEqual(response.status_code, 403)
|
|
||||||
|
|
||||||
@skip
|
|
||||||
def test_delete_mediafile_get_request(self):
|
|
||||||
clients = self.login_clients()
|
|
||||||
response = clients['client_manager'].get('/mediafiles/1/del/')
|
|
||||||
self.assertRedirects(response, expected_url='/mediafiles/1/edit/', status_code=302, target_status_code=200)
|
|
||||||
response = clients['client_vip_user'].get('/mediafiles/1/del/')
|
|
||||||
self.assertEqual(response.status_code, 403)
|
|
||||||
response = clients['client_normal_user'].get('/mediafiles/1/del/')
|
|
||||||
self.assertEqual(response.status_code, 403)
|
|
||||||
|
|
||||||
@skip
|
|
||||||
def test_delete_mediafile_get_request_own_file(self):
|
|
||||||
self.object.uploader = self.vip_user
|
|
||||||
self.object.save()
|
|
||||||
response = self.login_clients()['client_vip_user'].get('/mediafiles/1/del/')
|
|
||||||
self.assertRedirects(response, expected_url='/mediafiles/1/edit/', status_code=302, target_status_code=200)
|
|
||||||
|
|
||||||
@skip
|
|
||||||
def test_delete_mediafile_post_request(self):
|
|
||||||
tmpfile_no, mediafile_3_path = tempfile.mkstemp(prefix='tmp_openslides_test_', dir=self.tmp_dir)
|
|
||||||
os.close(tmpfile_no)
|
|
||||||
object_3 = Mediafile.objects.create(title='Title File 3', mediafile=mediafile_3_path)
|
|
||||||
client_1 = self.login_clients()['client_manager']
|
|
||||||
response_1 = client_1.post('/mediafiles/2/del/', {'yes': 'foo'})
|
|
||||||
self.assertRedirects(response_1, expected_url='/mediafiles/', status_code=302, target_status_code=200)
|
|
||||||
self.assertFalse(os.path.exists(object_3.mediafile.path))
|
|
||||||
|
|
||||||
@skip
|
|
||||||
def test_delete_mediafile_post_request_own_file(self):
|
|
||||||
tmpfile_no, mediafile_3_path = tempfile.mkstemp(prefix='tmp_openslides_test_', dir=self.tmp_dir)
|
|
||||||
os.close(tmpfile_no)
|
|
||||||
object_3 = Mediafile.objects.create(title='Title File 3b', mediafile=mediafile_3_path, uploader=self.vip_user)
|
|
||||||
client_1 = self.login_clients()['client_vip_user']
|
|
||||||
response_1 = client_1.post('/mediafiles/2/del/', {'yes': 'foo'})
|
|
||||||
self.assertRedirects(response_1, expected_url='/mediafiles/', status_code=302, target_status_code=200)
|
|
||||||
self.assertFalse(os.path.exists(object_3.mediafile.path))
|
|
||||||
|
|
||||||
@skip
|
|
||||||
def test_delete_mediafile_post_request_another_file(self):
|
|
||||||
tmpfile_no, mediafile_3_path = tempfile.mkstemp(prefix='tmp_openslides_test_', dir=self.tmp_dir)
|
|
||||||
os.close(tmpfile_no)
|
|
||||||
object_3 = Mediafile.objects.create(title='Title File 3c', mediafile=mediafile_3_path, uploader=self.normal_user)
|
|
||||||
client_1 = self.login_clients()['client_vip_user']
|
|
||||||
response = client_1.post('/mediafiles/2/del/', {'yes': 'foo'})
|
|
||||||
self.assertEqual(response.status_code, 403)
|
|
||||||
path_3 = object_3.mediafile.path
|
|
||||||
self.assertTrue(os.path.exists(path_3))
|
|
||||||
object_3.mediafile.delete()
|
|
||||||
self.assertFalse(os.path.exists(path_3))
|
|
||||||
|
|
||||||
def test_filesize(self):
|
|
||||||
tmpfile_no, mediafile_4_path = tempfile.mkstemp(prefix='tmp_openslides_test_', dir=self.tmp_dir)
|
|
||||||
os.close(tmpfile_no)
|
|
||||||
object_4 = Mediafile.objects.create(title='Title File 4', mediafile=mediafile_4_path)
|
|
||||||
self.assertEqual(object_4.get_filesize(), '< 1 kB')
|
|
||||||
with open(object_4.mediafile.path, 'wb') as bigfile:
|
|
||||||
bigfile.seek(2047)
|
|
||||||
bigfile.write(b'0')
|
|
||||||
self.assertEqual(object_4.get_filesize(), '2 kB')
|
|
||||||
with open(object_4.mediafile.path, 'wb') as bigfile:
|
|
||||||
bigfile.seek(1048575)
|
|
||||||
bigfile.write(b'0')
|
|
||||||
self.assertEqual(object_4.get_filesize(), '1 MB')
|
|
||||||
os.remove(mediafile_4_path)
|
|
||||||
self.assertEqual(object_4.get_filesize(), 'unknown')
|
|
@ -1 +0,0 @@
|
|||||||
default_app_config = 'tests.old.utils.apps.TestPluginAppConfig'
|
|
@ -1,6 +0,0 @@
|
|||||||
from django.apps import AppConfig
|
|
||||||
|
|
||||||
|
|
||||||
class TestPluginAppConfig(AppConfig):
|
|
||||||
name = 'tests.old.utils'
|
|
||||||
label = 'tests.old.utils'
|
|
@ -1,76 +0,0 @@
|
|||||||
from unittest.mock import patch
|
|
||||||
|
|
||||||
from django.dispatch import Signal
|
|
||||||
from django.test.client import RequestFactory
|
|
||||||
|
|
||||||
from openslides.utils.dispatch import SignalConnectMetaClass
|
|
||||||
from openslides.utils.test import TestCase
|
|
||||||
|
|
||||||
|
|
||||||
class TestBaseOne(object, metaclass=SignalConnectMetaClass):
|
|
||||||
signal = Signal()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_dispatch_uid(cls):
|
|
||||||
if not cls.__name__ == 'TestBaseOne':
|
|
||||||
return 'test_vieM1eingi6luish5Sei'
|
|
||||||
|
|
||||||
|
|
||||||
class TestBaseTwo(object, metaclass=SignalConnectMetaClass):
|
|
||||||
signal = Signal()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_dispatch_uid(cls):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class TestSignalConnectMetaClass(TestCase):
|
|
||||||
request_factory = RequestFactory()
|
|
||||||
|
|
||||||
@patch('tests.old.utils.test_dispatch.TestBaseOne.signal')
|
|
||||||
def test_call_signal_send(self, mock_signal):
|
|
||||||
TestBaseOne.get_all(self.request_factory.request)
|
|
||||||
self.assertTrue(mock_signal.send.called)
|
|
||||||
|
|
||||||
@patch('tests.old.utils.test_dispatch.TestBaseOne.signal')
|
|
||||||
def test_call_signal_connect(self, mock_signal):
|
|
||||||
class TestChildOne(TestBaseOne):
|
|
||||||
pass
|
|
||||||
|
|
||||||
self.assertTrue(mock_signal.connect.called)
|
|
||||||
self.assertEqual(mock_signal.connect.call_args[0][0], TestChildOne)
|
|
||||||
self.assertEqual(mock_signal.connect.call_args[1], dict(dispatch_uid='test_vieM1eingi6luish5Sei'))
|
|
||||||
|
|
||||||
def test_bad_base_class(self):
|
|
||||||
def wrapper():
|
|
||||||
class BadClass1(object, metaclass=SignalConnectMetaClass):
|
|
||||||
pass
|
|
||||||
|
|
||||||
self.assertRaisesMessage(
|
|
||||||
NotImplementedError,
|
|
||||||
'Your class BadClass1 must have a get_dispatch_uid classmethod.',
|
|
||||||
wrapper)
|
|
||||||
|
|
||||||
def test_bad_base_class_without_signal(self):
|
|
||||||
def wrapper():
|
|
||||||
class BadClass2(object, metaclass=SignalConnectMetaClass):
|
|
||||||
@classmethod
|
|
||||||
def get_dispatch_uid(cls):
|
|
||||||
return True
|
|
||||||
|
|
||||||
self.assertRaisesMessage(
|
|
||||||
NotImplementedError,
|
|
||||||
'Your class BadClass2 must have a signal argument, which must be a Django Signal instance.',
|
|
||||||
wrapper)
|
|
||||||
|
|
||||||
def test_receive_signal(self):
|
|
||||||
class TestChildTwo(TestBaseTwo):
|
|
||||||
def __init__(self, sender, **kwargs):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_dispatch_uid(self):
|
|
||||||
return 'test_leeve5eighahT3zooxe5'
|
|
||||||
|
|
||||||
childtwo = TestBaseTwo.get_all(self.request_factory.request)[0]
|
|
||||||
self.assertEqual(type(childtwo), TestChildTwo)
|
|
Loading…
Reference in New Issue
Block a user