From ee3e2a5d3f38a2a686ffc74ece99f4a35053bd13 Mon Sep 17 00:00:00 2001 From: lennertvandevelde Date: Wed, 3 May 2023 10:26:56 +0200 Subject: [PATCH] Adds a Mediahaven Query class --- mediahaven/__init__.py | 55 +++++++++++++++- tests/test_query.py | 145 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+), 2 deletions(-) create mode 100644 tests/test_query.py diff --git a/mediahaven/__init__.py b/mediahaven/__init__.py index b691a44..0541c37 100644 --- a/mediahaven/__init__.py +++ b/mediahaven/__init__.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from typing import List, Tuple, Union from mediahaven.mediahaven import MediaHavenClient @@ -13,5 +14,55 @@ class MediaHaven(MediaHavenClient): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.records = Records(self) - self.fields = FieldDefinitions(self) - self.organisations = Organisations(self) \ No newline at end of file + self.field_definitions = FieldDefinitions(self) + self.organisations = Organisations(self) + +class MediaHavenQuery: + "MediaHaven query object." + + def __init__(self, ): + self._clauses = [] + + def add_clauses(self, query_params: Union[List[Tuple[str, str]], List[str]] , exclude: bool = False, is_and: bool = False): + """Adds clauses to the query. + + Args: + query_params: A list of tuples containing the query parameters (field and value), or a string containing free text. + exclude: If true the clauses will be excluded from the query. + is_and: If true the clauses will be combined with an AND operator, otherwise with an OR operator. + """ + + + self._clauses.append( + { + "query_params": query_params, + "operator": ("-" if exclude else "+"), + "is_and": is_and + } + ) + + def generate_query(self) -> str: + """Generates the query string. + + Returns: + The query string. + """ + + query = " ".join( + [ + f'{clause["operator"]}(' + ' '.join( + [f'{k_v[0]}:"{k_v[1]}"' for k_v in clause["query_params"]] + if isinstance(clause["query_params"][0], Tuple) + else [f'{v}' for v in clause["query_params"]] + ) + ')' + if not clause["is_and"] + else " ".join( + [f'{clause["operator"]}({k_v[0]}:"{k_v[1]}")' for k_v in clause["query_params"]] + if isinstance(clause["query_params"][0], Tuple) + else [f'{clause["operator"]}({v})' for v in clause["query_params"]] + ) + for clause in self._clauses + ] + ) + + return query \ No newline at end of file diff --git a/tests/test_query.py b/tests/test_query.py new file mode 100644 index 0000000..998f836 --- /dev/null +++ b/tests/test_query.py @@ -0,0 +1,145 @@ +import pytest +from unittest.mock import patch + +from mediahaven import MediaHavenQuery + +class TestQuery: + @pytest.fixture() + def query(self): + return MediaHavenQuery() + + def test_include_or(self, query: MediaHavenQuery): + # Arrange + query_params = [ + ("dc_title", "title1"), + ("dc_title", "title2"), + ] + query.add_clauses(query_params) + + #Act + query_string = query.generate_query() + + #Assert + assert query_string == '+(dc_title:"title1" dc_title:"title2")' + + def test_include_and(self, query: MediaHavenQuery): + # Arrange + query_params = [ + ("dc_title", "title1"), + ("dc_title", "title2"), + ] + query.add_clauses(query_params, is_and=True) + + #Act + query_string = query.generate_query() + + #Assert + assert query_string == '+(dc_title:"title1") +(dc_title:"title2")' + + def test_exclude_or(self, query: MediaHavenQuery): + # Arrange + query_params = [ + ("dc_title", "title1"), + ("dc_title", "title2"), + ] + query.add_clauses(query_params, exclude=True) + + #Act + query_string = query.generate_query() + + #Assert + assert query_string == '-(dc_title:"title1" dc_title:"title2")' + + def test_exclude_and(self, query: MediaHavenQuery): + # Arrange + query_params = [ + ("dc_title", "title1"), + ("dc_title", "title2"), + ] + query.add_clauses(query_params, exclude=True, is_and=True) + + #Act + query_string = query.generate_query() + + #Assert + assert query_string == '-(dc_title:"title1") -(dc_title:"title2")' + + def test_include_and_exclude_or(self, query: MediaHavenQuery): + # Arrange + query_params_1 = [ + ("dc_title", "title1"), + ("dc_title", "title2"), + ] + query.add_clauses(query_params_1, is_and=True) + + query_params_2 = [ + ("dc_description", "description1"), + ("dc_description", "description2"), + ] + query.add_clauses(query_params_2, exclude=True) + + #Act + query_string = query.generate_query() + + #Assert + assert query_string == '+(dc_title:"title1") +(dc_title:"title2") -(dc_description:"description1" dc_description:"description2")' + + def test_include_or_exclude_and(self, query: MediaHavenQuery): + # Arrange + query_params_1 = [ + ("dc_title", "title1"), + ("dc_title", "title2"), + ] + query.add_clauses(query_params_1) + + query_params_2 = [ + ("dc_description", "description1"), + ("dc_description", "description2"), + ] + query.add_clauses(query_params_2, exclude=True, is_and=True) + + #Act + query_string = query.generate_query() + + #Assert + assert query_string == '+(dc_title:"title1" dc_title:"title2") -(dc_description:"description1") -(dc_description:"description2")' + + def test_include_and_exclude_and(self, query: MediaHavenQuery): + # Arrange + query_params_1 = [ + ("dc_title", "title1"), + ("dc_title", "title2"), + ] + query.add_clauses(query_params_1, is_and=True) + + query_params_2 = [ + ("dc_description", "description1"), + ("dc_description", "description2"), + ] + query.add_clauses(query_params_2, exclude=True, is_and=True) + + #Act + query_string = query.generate_query() + + #Assert + assert query_string == '+(dc_title:"title1") +(dc_title:"title2") -(dc_description:"description1") -(dc_description:"description2")' + + def test_include_or_exclude_or(self, query: MediaHavenQuery): + # Arrange + query_params_1 = [ + ("dc_title", "title1"), + ("dc_title", "title2"), + ] + query.add_clauses(query_params_1) + + query_params_2 = [ + ("dc_description", "description1"), + ("dc_description", "description2"), + ] + query.add_clauses(query_params_2, exclude=True) + + #Act + query_string = query.generate_query() + + #Assert + assert query_string == '+(dc_title:"title1" dc_title:"title2") -(dc_description:"description1" dc_description:"description2")'