Make Consumer real async again
This commit is contained in:
parent
8adaa6118a
commit
732de97ec2
@ -4,6 +4,7 @@ from typing import Any, Dict, List
|
|||||||
|
|
||||||
from django.apps import AppConfig
|
from django.apps import AppConfig
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.db.models.signals import post_migrate
|
from django.db.models.signals import post_migrate
|
||||||
|
|
||||||
from ..utils.projector import register_projector_elements
|
from ..utils.projector import register_projector_elements
|
||||||
@ -37,6 +38,14 @@ class CoreAppConfig(AppConfig):
|
|||||||
ProjectorViewSet,
|
ProjectorViewSet,
|
||||||
TagViewSet,
|
TagViewSet,
|
||||||
)
|
)
|
||||||
|
from ..utils.constants import set_constants, get_constants_from_apps
|
||||||
|
|
||||||
|
# Set constants
|
||||||
|
try:
|
||||||
|
set_constants(get_constants_from_apps())
|
||||||
|
except ImproperlyConfigured:
|
||||||
|
# Database is not loaded. This happens in tests.
|
||||||
|
pass
|
||||||
|
|
||||||
# Define config variables and projector elements.
|
# Define config variables and projector elements.
|
||||||
config.update_config_variables(get_config_variables())
|
config.update_config_variables(get_config_variables())
|
||||||
|
@ -48,6 +48,7 @@ from .models import (
|
|||||||
ProjectorMessage,
|
ProjectorMessage,
|
||||||
Tag,
|
Tag,
|
||||||
)
|
)
|
||||||
|
from ..utils.constants import get_constants
|
||||||
|
|
||||||
|
|
||||||
# Special Django views
|
# Special Django views
|
||||||
@ -133,15 +134,7 @@ class WebclientJavaScriptView(utils_views.View):
|
|||||||
|
|
||||||
# angular constants
|
# angular constants
|
||||||
angular_constants = ''
|
angular_constants = ''
|
||||||
for app in apps.get_app_configs():
|
for key, value in get_constants().items():
|
||||||
try:
|
|
||||||
# Each app can deliver values to angular when implementing this method.
|
|
||||||
# It should return a list with dicts containing the 'name' and 'value'.
|
|
||||||
get_angular_constants = app.get_angular_constants
|
|
||||||
except AttributeError:
|
|
||||||
# The app doesn't have this method. Continue to next app.
|
|
||||||
continue
|
|
||||||
for key, value in get_angular_constants().items():
|
|
||||||
value = json.dumps(value)
|
value = json.dumps(value)
|
||||||
angular_constants += ".constant('{}', {})".format(key, value)
|
angular_constants += ".constant('{}', {})".format(key, value)
|
||||||
|
|
||||||
|
40
openslides/utils/constants.py
Normal file
40
openslides/utils/constants.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
from typing import Any, Dict
|
||||||
|
|
||||||
|
from django.apps import apps
|
||||||
|
|
||||||
|
|
||||||
|
def get_constants_from_apps() -> Dict[str, Any]:
|
||||||
|
out: Dict[str, Any] = {}
|
||||||
|
for app in apps.get_app_configs():
|
||||||
|
try:
|
||||||
|
# Each app can deliver values to angular when implementing this method.
|
||||||
|
# It should return a list with dicts containing the 'name' and 'value'.
|
||||||
|
get_angular_constants = app.get_angular_constants
|
||||||
|
except AttributeError:
|
||||||
|
# The app doesn't have this method. Continue to next app.
|
||||||
|
continue
|
||||||
|
out.update(get_angular_constants())
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
constants = None
|
||||||
|
|
||||||
|
|
||||||
|
def get_constants() -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
Returns the constants.
|
||||||
|
|
||||||
|
This method only returns a static dict, so it is fast and can be used in a
|
||||||
|
async context.
|
||||||
|
"""
|
||||||
|
if constants is None:
|
||||||
|
raise RuntimeError("Constants are not set.")
|
||||||
|
return constants
|
||||||
|
|
||||||
|
|
||||||
|
def set_constants(value: Dict[str, Any]) -> None:
|
||||||
|
"""
|
||||||
|
Sets the constants variable.
|
||||||
|
"""
|
||||||
|
global constants
|
||||||
|
constants = value
|
@ -4,7 +4,6 @@ import jsonschema
|
|||||||
from asgiref.sync import sync_to_async
|
from asgiref.sync import sync_to_async
|
||||||
from channels.db import database_sync_to_async
|
from channels.db import database_sync_to_async
|
||||||
from channels.generic.websocket import AsyncJsonWebsocketConsumer
|
from channels.generic.websocket import AsyncJsonWebsocketConsumer
|
||||||
from django.apps import apps
|
|
||||||
|
|
||||||
from ..core.config import config
|
from ..core.config import config
|
||||||
from ..core.models import Projector
|
from ..core.models import Projector
|
||||||
@ -16,6 +15,7 @@ from .collection import (
|
|||||||
format_for_autoupdate,
|
format_for_autoupdate,
|
||||||
from_channel_message,
|
from_channel_message,
|
||||||
)
|
)
|
||||||
|
from .constants import get_constants
|
||||||
|
|
||||||
|
|
||||||
class ProtocollAsyncJsonWebsocketConsumer(AsyncJsonWebsocketConsumer):
|
class ProtocollAsyncJsonWebsocketConsumer(AsyncJsonWebsocketConsumer):
|
||||||
@ -31,7 +31,7 @@ class ProtocollAsyncJsonWebsocketConsumer(AsyncJsonWebsocketConsumer):
|
|||||||
"type": {
|
"type": {
|
||||||
"description": "Defines what kind of packages is packed.",
|
"description": "Defines what kind of packages is packed.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"pattern": "notify|constantsRequest", # The server can sent other types
|
"pattern": "notify|constants", # The server can sent other types
|
||||||
},
|
},
|
||||||
"content": {
|
"content": {
|
||||||
"description": "The content of the package.",
|
"description": "The content of the package.",
|
||||||
@ -137,19 +137,10 @@ class SiteConsumer(ProtocollAsyncJsonWebsocketConsumer):
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
await self.send_json(type='error', content='Invalid notify message', in_response=id)
|
await self.send_json(type='error', content='Invalid notify message', in_response=id)
|
||||||
elif type == 'constantsRequest':
|
|
||||||
angular_constants: Dict[str, Any] = {}
|
elif type == 'constants':
|
||||||
for app in apps.get_app_configs():
|
# Return all constants to the client.
|
||||||
try:
|
await self.send_json(type='constants', content=get_constants(), in_response=id)
|
||||||
# Each app can deliver values to angular when implementing this method.
|
|
||||||
# It should return a list with dicts containing the 'name' and 'value'.
|
|
||||||
get_angular_constants = app.get_angular_constants
|
|
||||||
except AttributeError:
|
|
||||||
# The app doesn't have this method. Continue to next app.
|
|
||||||
continue
|
|
||||||
constants = await database_sync_to_async(get_angular_constants)()
|
|
||||||
angular_constants.update(constants)
|
|
||||||
await self.send_json(type='constantsResponse', content=angular_constants, in_response=id)
|
|
||||||
|
|
||||||
async def send_notify(self, event: Dict[str, Any]) -> None:
|
async def send_notify(self, event: Dict[str, Any]) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
|
import pytest
|
||||||
from django.test import TestCase, TransactionTestCase
|
from django.test import TestCase, TransactionTestCase
|
||||||
|
from pytest_django.django_compat import is_django_unittest
|
||||||
from pytest_django.plugin import validate_django_db
|
from pytest_django.plugin import validate_django_db
|
||||||
|
|
||||||
|
|
||||||
@ -38,3 +40,20 @@ def pytest_collection_modifyitems(items):
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
items.sort(key=weight_test_case)
|
items.sort(key=weight_test_case)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def constants(request):
|
||||||
|
"""
|
||||||
|
Resets the constants on every test.
|
||||||
|
|
||||||
|
Uses fake constants, if the db is not in use.
|
||||||
|
"""
|
||||||
|
from openslides.utils.constants import set_constants, get_constants_from_apps
|
||||||
|
|
||||||
|
if 'django_db' in request.node.keywords or is_django_unittest(request):
|
||||||
|
# When the db is created, use the original constants
|
||||||
|
set_constants(get_constants_from_apps())
|
||||||
|
else:
|
||||||
|
# Else: Use fake constants
|
||||||
|
set_constants({'constant1': 'value1', 'constant2': 'value2'})
|
||||||
|
@ -241,3 +241,18 @@ async def test_send_unknown_type(communicator):
|
|||||||
response = await communicator.receive_json_from()
|
response = await communicator.receive_json_from()
|
||||||
assert response['type'] == 'error'
|
assert response['type'] == 'error'
|
||||||
assert response['in_response'] == 'test_id'
|
assert response['in_response'] == 'test_id'
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_request_constants(communicator, settings):
|
||||||
|
await set_config('general_system_enable_anonymous', True)
|
||||||
|
await communicator.connect()
|
||||||
|
# Await the startup data
|
||||||
|
await communicator.receive_json_from()
|
||||||
|
|
||||||
|
await communicator.send_json_to({'type': 'constants', 'content': '', 'id': 'test_id'})
|
||||||
|
|
||||||
|
response = await communicator.receive_json_from()
|
||||||
|
assert response['type'] == 'constants'
|
||||||
|
# See conftest.py for the content of 'content'
|
||||||
|
assert response['content'] == {'constant1': 'value1', 'constant2': 'value2'}
|
||||||
|
Loading…
Reference in New Issue
Block a user