From 6605934a3372e071d4114b2a46a5c7ac7df1ea6e Mon Sep 17 00:00:00 2001 From: jsangmeister Date: Fri, 1 Nov 2019 09:11:12 +0100 Subject: [PATCH] added count query decorator --- openslides/motions/views.py | 4 +- openslides/utils/cache.py | 6 +- tests/count_queries.py | 32 ++++++++ tests/integration/agenda/test_viewset.py | 2 +- tests/integration/assignments/test_polls.py | 5 +- tests/integration/assignments/test_viewset.py | 3 +- tests/integration/core/test_viewset.py | 3 +- tests/integration/helpers.py | 17 ----- tests/integration/mediafiles/test_viewset.py | 3 +- tests/integration/motions/test_motions.py | 76 ++++++++++++++++++- tests/integration/motions/test_polls.py | 3 +- tests/integration/motions/test_viewset.py | 3 +- tests/integration/topics/test_viewset.py | 3 +- tests/integration/users/test_viewset.py | 2 +- 14 files changed, 123 insertions(+), 39 deletions(-) create mode 100644 tests/count_queries.py diff --git a/openslides/motions/views.py b/openslides/motions/views.py index 629f8a3cf..bc98d956b 100644 --- a/openslides/motions/views.py +++ b/openslides/motions/views.py @@ -192,9 +192,7 @@ class MotionViewSet(TreeSortMixin, ModelViewSet): if isinstance(request.data, QueryDict): submitters_id = request.data.getlist("submitters_id") else: - submitters_id = request.data.get("submitters_id") - if submitters_id is None: - submitters_id = [] + submitters_id = request.data.get("submitters_id", []) if not isinstance(submitters_id, list): raise ValidationError( {"detail": "If submitters_id is given, it has to be a list."} diff --git a/openslides/utils/cache.py b/openslides/utils/cache.py index 2cf03d41b..92cc0385a 100644 --- a/openslides/utils/cache.py +++ b/openslides/utils/cache.py @@ -329,7 +329,11 @@ class ElementCache: for collection_string, value_list in raw_changed_elements.items() } - if user_id is not None: + if user_id is None: + for elements in changed_elements.values(): + for element in elements: + element.pop("_no_delete_on_restriction", False) + else: # the list(...) is important, because `changed_elements` will be # altered during iteration and restricting data for collection_string, elements in list(changed_elements.items()): diff --git a/tests/count_queries.py b/tests/count_queries.py new file mode 100644 index 000000000..4f207652d --- /dev/null +++ b/tests/count_queries.py @@ -0,0 +1,32 @@ +from django.db import DEFAULT_DB_ALIAS, connections +from django.test.utils import CaptureQueriesContext + + +def count_queries(func, verbose=False, *args, **kwargs) -> int: + context = CaptureQueriesContext(connections[DEFAULT_DB_ALIAS]) + with context: + func(*args, **kwargs) + + if verbose: + queries = "\n".join( + f"{i}. {query['sql']}" + for i, query in enumerate(context.captured_queries, start=1) + ) + print(f"{len(context)} queries executed\nCaptured queries were:\n{queries}") + + return len(context) + + +def assert_query_count(should_be, verbose=False): + """ + Decorator to easily count queries on any test you want. + should_be defines how many queries are to be expected + """ + + def outer(func): + def inner(*args, **kwargs): + assert count_queries(func, verbose, *args, **kwargs) == should_be + + return inner + + return outer diff --git a/tests/integration/agenda/test_viewset.py b/tests/integration/agenda/test_viewset.py index b0b898a3d..5f38a18f4 100644 --- a/tests/integration/agenda/test_viewset.py +++ b/tests/integration/agenda/test_viewset.py @@ -16,10 +16,10 @@ from openslides.motions.models import Motion from openslides.topics.models import Topic from openslides.users.models import Group from openslides.utils.autoupdate import inform_changed_data +from tests.count_queries import count_queries from tests.test_case import TestCase from ...common_groups import GROUP_DEFAULT_PK -from ..helpers import count_queries class ContentObjects(TestCase): diff --git a/tests/integration/assignments/test_polls.py b/tests/integration/assignments/test_polls.py index acdc1d7ca..0a48ee504 100644 --- a/tests/integration/assignments/test_polls.py +++ b/tests/integration/assignments/test_polls.py @@ -18,10 +18,9 @@ from openslides.poll.models import BasePoll from openslides.utils.auth import get_group_model from openslides.utils.autoupdate import inform_changed_data from tests.common_groups import GROUP_ADMIN_PK, GROUP_DELEGATE_PK +from tests.count_queries import assert_query_count, count_queries from tests.test_case import TestCase -from ..helpers import count_queries - @pytest.mark.django_db(transaction=False) def test_assignment_poll_db_queries(): @@ -95,6 +94,8 @@ class CreateAssignmentPoll(TestCase): ) self.assignment.add_candidate(self.admin) + # TODO lower query count + @assert_query_count(47, True) def test_simple(self): response = self.client.post( reverse("assignmentpoll-list"), diff --git a/tests/integration/assignments/test_viewset.py b/tests/integration/assignments/test_viewset.py index eb837226c..9474f28c7 100644 --- a/tests/integration/assignments/test_viewset.py +++ b/tests/integration/assignments/test_viewset.py @@ -9,10 +9,9 @@ from openslides.assignments.models import Assignment from openslides.core.models import Tag from openslides.mediafiles.models import Mediafile from openslides.utils.autoupdate import inform_changed_data +from tests.count_queries import count_queries from tests.test_case import TestCase -from ..helpers import count_queries - @pytest.mark.django_db(transaction=False) def test_assignment_db_queries(): diff --git a/tests/integration/core/test_viewset.py b/tests/integration/core/test_viewset.py index a8a2e2111..568422df9 100644 --- a/tests/integration/core/test_viewset.py +++ b/tests/integration/core/test_viewset.py @@ -14,10 +14,9 @@ from openslides.users.models import User from openslides.utils.auth import get_group_model from openslides.utils.autoupdate import inform_changed_data from tests.common_groups import GROUP_ADMIN_PK, GROUP_DELEGATE_PK +from tests.count_queries import count_queries from tests.test_case import TestCase -from ..helpers import count_queries - @pytest.mark.django_db(transaction=False) def test_projector_db_queries(): diff --git a/tests/integration/helpers.py b/tests/integration/helpers.py index d961f9a73..f83011d6e 100644 --- a/tests/integration/helpers.py +++ b/tests/integration/helpers.py @@ -1,8 +1,5 @@ from typing import Any, Dict, List -from django.db import DEFAULT_DB_ALIAS, connections -from django.test.utils import CaptureQueriesContext - from openslides.core.config import config from openslides.core.models import Projector from openslides.users.models import User @@ -118,20 +115,6 @@ register_projector_slide("test/slide1", slide1) register_projector_slide("test/slide2", slide2) -def count_queries(func, *args, **kwargs) -> int: - context = CaptureQueriesContext(connections[DEFAULT_DB_ALIAS]) - with context: - func(*args, **kwargs) - - queries = "\n".join( - f"{i}. {query['sql']}" - for i, query in enumerate(context.captured_queries, start=1) - ) - - print(f"{len(context)} queries executed\nCaptured queries were:\n{queries}") - return len(context) - - def all_data_config() -> AllData: return { TConfig().get_collection_string(): { diff --git a/tests/integration/mediafiles/test_viewset.py b/tests/integration/mediafiles/test_viewset.py index eaa74bad1..f7c37d4c8 100644 --- a/tests/integration/mediafiles/test_viewset.py +++ b/tests/integration/mediafiles/test_viewset.py @@ -7,10 +7,9 @@ from rest_framework import status from rest_framework.test import APIClient from openslides.mediafiles.models import Mediafile +from tests.count_queries import count_queries from tests.test_case import TestCase -from ..helpers import count_queries - @pytest.mark.django_db(transaction=False) def test_mediafiles_db_queries(): diff --git a/tests/integration/motions/test_motions.py b/tests/integration/motions/test_motions.py index 026353ae9..b8dce6966 100644 --- a/tests/integration/motions/test_motions.py +++ b/tests/integration/motions/test_motions.py @@ -24,10 +24,9 @@ from openslides.poll.models import BasePoll from openslides.utils.auth import get_group_model from openslides.utils.autoupdate import inform_changed_data from tests.common_groups import GROUP_ADMIN_PK, GROUP_DEFAULT_PK, GROUP_DELEGATE_PK +from tests.count_queries import assert_query_count, count_queries from tests.test_case import TestCase -from ..helpers import count_queries - @pytest.mark.django_db(transaction=False) def test_motion_db_queries(): @@ -126,10 +125,13 @@ class CreateMotion(TestCase): Tests motion creation. """ + maxDiff = None + def setUp(self): self.client = APIClient() self.client.login(username="admin", password="admin") + @assert_query_count(85, True) def test_simple(self): """ Tests that a motion is created with a specific title and text. @@ -146,6 +148,76 @@ class CreateMotion(TestCase): ) self.assertEqual(response.status_code, status.HTTP_201_CREATED) motion = Motion.objects.get() + changed_autoupdate, deleted_autoupdate = self.get_last_autoupdate() + del changed_autoupdate["motions/motion:1"]["created"] + del changed_autoupdate["motions/motion:1"]["last_modified"] + self.assertEqual( + changed_autoupdate, + { + "agenda/list-of-speakers:1": { + "id": 1, + "title_information": { + "title": "test_title_OoCoo3MeiT9li5Iengu9", + "identifier": "1", + }, + "speakers": [], + "closed": False, + "content_object": {"collection": "motions/motion", "id": 1}, + }, + "motions/motion:1": { + "id": 1, + "identifier": "1", + "title": "test_title_OoCoo3MeiT9li5Iengu9", + "text": "test_text_thuoz0iecheiheereiCi", + "amendment_paragraphs": None, + "modified_final_version": "", + "reason": "", + "parent_id": None, + "category_id": None, + "category_weight": 10000, + "comments": [], + "motion_block_id": None, + "origin": "", + "submitters": [ + {"id": 1, "user_id": 1, "motion_id": 1, "weight": 1} + ], + "supporters_id": [], + "state_id": 1, + "state_extension": None, + "state_restriction": [], + "statute_paragraph_id": None, + "workflow_id": 1, + "recommendation_id": None, + "recommendation_extension": None, + "tags_id": [], + "attachments_id": [], + "agenda_item_id": 1, + "list_of_speakers_id": 1, + "sort_parent_id": None, + "weight": 10000, + "change_recommendations_id": [], + }, + "agenda/item:1": { + "id": 1, + "item_number": "", + "title_information": { + "title": "test_title_OoCoo3MeiT9li5Iengu9", + "identifier": "1", + }, + "comment": None, + "closed": False, + "type": 3, + "is_internal": False, + "is_hidden": True, + "duration": None, + "content_object": {"collection": "motions/motion", "id": 1}, + "weight": 10000, + "parent_id": None, + "level": 0, + }, + }, + ) + self.assertEqual(deleted_autoupdate, []) self.assertEqual(motion.title, "test_title_OoCoo3MeiT9li5Iengu9") self.assertEqual(motion.identifier, "1") self.assertTrue(motion.submitters.exists()) diff --git a/tests/integration/motions/test_polls.py b/tests/integration/motions/test_polls.py index 66c6a320d..25fad2578 100644 --- a/tests/integration/motions/test_polls.py +++ b/tests/integration/motions/test_polls.py @@ -12,10 +12,9 @@ from openslides.poll.models import BasePoll from openslides.utils.auth import get_group_model from openslides.utils.autoupdate import inform_changed_data from tests.common_groups import GROUP_ADMIN_PK, GROUP_DEFAULT_PK, GROUP_DELEGATE_PK +from tests.count_queries import count_queries from tests.test_case import TestCase -from ..helpers import count_queries - @pytest.mark.django_db(transaction=False) def test_motion_poll_db_queries(): diff --git a/tests/integration/motions/test_viewset.py b/tests/integration/motions/test_viewset.py index af91831eb..ac71efa21 100644 --- a/tests/integration/motions/test_viewset.py +++ b/tests/integration/motions/test_viewset.py @@ -19,10 +19,9 @@ from openslides.motions.models import ( from openslides.utils.auth import get_group_model from openslides.utils.autoupdate import inform_changed_data from tests.common_groups import GROUP_ADMIN_PK, GROUP_DELEGATE_PK, GROUP_STAFF_PK +from tests.count_queries import count_queries from tests.test_case import TestCase -from ..helpers import count_queries - @pytest.mark.django_db(transaction=False) def test_category_db_queries(): diff --git a/tests/integration/topics/test_viewset.py b/tests/integration/topics/test_viewset.py index 04a6f5641..c9d2cc8a0 100644 --- a/tests/integration/topics/test_viewset.py +++ b/tests/integration/topics/test_viewset.py @@ -4,10 +4,9 @@ from rest_framework import status from openslides.agenda.models import Item from openslides.topics.models import Topic +from tests.count_queries import count_queries from tests.test_case import TestCase -from ..helpers import count_queries - @pytest.mark.django_db(transaction=False) def test_topic_item_db_queries(): diff --git a/tests/integration/users/test_viewset.py b/tests/integration/users/test_viewset.py index f57322881..3a8ce3be6 100644 --- a/tests/integration/users/test_viewset.py +++ b/tests/integration/users/test_viewset.py @@ -8,6 +8,7 @@ from rest_framework.test import APIClient from openslides.core.config import config from openslides.users.models import Group, PersonalNote, User from openslides.utils.autoupdate import inform_changed_data +from tests.count_queries import count_queries from tests.test_case import TestCase from ...common_groups import ( @@ -16,7 +17,6 @@ from ...common_groups import ( GROUP_DELEGATE_PK, GROUP_STAFF_PK, ) -from ..helpers import count_queries @pytest.mark.django_db(transaction=False)