From d48d8b47a453eacf8de3f83d18a4c23d84a3d470 Mon Sep 17 00:00:00 2001 From: lukas leufen <l.leufen@fz-juelich.de> Date: Fri, 22 Nov 2019 18:19:44 +0100 Subject: [PATCH] added method search_scope --- src/datastore.py | 77 ++++++++++++++++++++++++++++++++++++++++-- test/test_datastore.py | 55 +++++++++++++++++++++++++++++- 2 files changed, 128 insertions(+), 4 deletions(-) diff --git a/src/datastore.py b/src/datastore.py index b106c767..c6f200bb 100644 --- a/src/datastore.py +++ b/src/datastore.py @@ -20,6 +20,13 @@ class NameNotFoundInScope(Exception): pass +class EmptyScope(Exception): + """ + Exception that get raised if given scope is not part of the data store. + """ + pass + + class AbstractDataStore(ABC): """ @@ -57,6 +64,21 @@ class AbstractDataStore(ABC): """ pass + def search_scope(self, scope: str) -> None: + """ + Abstract method to search for all object names that are stored for given scope + :param scope: scope to look for + :return: search result + """ + pass + + def list_all_scopes(self) -> None: + """ + Abstract method to list all scopes in data store + :return: all found scopes + """ + pass + class DataStoreByVariable(AbstractDataStore): @@ -106,10 +128,11 @@ class DataStoreByVariable(AbstractDataStore): except KeyError: return self.get(name, scope.rsplit(".", maxsplit=depth)[0], depth-1) else: - if name in self._store.keys(): + try: + occurrences = self.search_name(name) raise NameNotFoundInScope(f"Couldn't find {name} in scope {scope}. {name} is only defined in " - f"{self.search_name(name)}") - else: + f"{occurrences}") + except KeyError: raise NameNotFoundInDataStore(f"Couldn't find {name} in data store") def search_name(self, name: str) -> List[str]: @@ -120,6 +143,34 @@ class DataStoreByVariable(AbstractDataStore): """ return sorted(self._store[name]) + def search_scope(self, scope: str) -> List[str]: + """ + Search for given `scope` and list all object names stored under this scope. + :param scope: scope to look for + :return: list with all object names + """ + names = [] + for (k, v) in self._store.items(): + if scope in v.keys(): + names.append(k) + if len(names) > 0: + return sorted(names) + else: + raise EmptyScope(f"Given scope {scope} is not part of the data store. Available scopes are: " + f"{self.list_all_scopes()}") + + def list_all_scopes(self) -> List[str]: + """ + List all available scopes in data store + :return: names of all stored objects + """ + scopes = [] + for v in self._store.values(): + for scope in v.keys(): + if scope not in scopes: + scopes.append(scope) + return sorted(scopes) + class DataStoreByScope(AbstractDataStore): @@ -175,6 +226,8 @@ class DataStoreByScope(AbstractDataStore): raise NameNotFoundInScope(f"Couldn't find {name} in scope {scope}. {name} is only defined in " f"{occurrences}") + + def search_name(self, name: str) -> List[str]: """ Search for all occurrences of given `name` in the entire data store. @@ -187,4 +240,22 @@ class DataStoreByScope(AbstractDataStore): keys.append(key) return sorted(keys) + def search_scope(self, scope: str, current_scope_only=True) -> List[str]: + """ + Search for given `scope` and list all object names stored under this scope. + :param scope: scope to look for + :return: list with all object names + """ + try: + return sorted(self._store[scope].keys()) + except KeyError: + raise EmptyScope(f"Given scope {scope} is not part of the data store. Available scopes are: " + f"{self.list_all_scopes()}") + + def list_all_scopes(self) -> List[str]: + """ + List all available scopes in data store + :return: names of all stored objects + """ + return sorted(self._store.keys()) diff --git a/test/test_datastore.py b/test/test_datastore.py index 1c41b18c..1434508b 100644 --- a/test/test_datastore.py +++ b/test/test_datastore.py @@ -3,7 +3,7 @@ __date__ = '2019-11-22' from src.datastore import AbstractDataStore, DataStoreByVariable, DataStoreByScope -from src.datastore import NameNotFoundInDataStore, NameNotFoundInScope +from src.datastore import NameNotFoundInDataStore, NameNotFoundInScope, EmptyScope import pytest @@ -61,6 +61,28 @@ class TestDataStoreByVariable: ds.get("number", "general") assert "Couldn't find number in scope general. number is only defined in ['general.sub']" in e.value.args[0] + def test_list_all_scopes(self, ds): + ds.put("number", 22, "general2") + ds.put("number", 11, "general.sub") + ds.put("number", 3, "general.sub3") + ds.put("number", 1, "general") + assert ds.list_all_scopes() == ['general', 'general.sub', 'general.sub3', 'general2'] + + def test_search_scope(self, ds): + ds.put("number", 22, "general") + ds.put("number", 11, "general.sub") + ds.put("number1", 22, "general.sub") + ds.put("number2", 3, "general.sub.sub") + assert ds.search_scope("general.sub") == ["number", "number1"] + + def test_search_empty_scope(self, ds): + ds.put("number", 22, "general2") + ds.put("number", 11, "general.sub") + with pytest.raises(EmptyScope) as e: + ds.search_scope("general.sub2") + assert "Given scope general.sub2 is not part of the data store." in e.value.args[0] + assert "Available scopes are: ['general.sub', 'general2']" in e.value.args[0] + class TestDataStoreByScope: @@ -105,3 +127,34 @@ class TestDataStoreByScope: with pytest.raises(NameNotFoundInScope) as e: ds.get("number", "general") assert "Couldn't find number in scope general. number is only defined in ['general.sub']" in e.value.args[0] + + def test_list_all_scopes(self, ds): + ds.put("number", 22, "general2") + ds.put("number", 11, "general.sub") + ds.put("number", 3, "general.sub3") + ds.put("number", 1, "general") + assert ds.list_all_scopes() == ['general', 'general.sub', 'general.sub3', 'general2'] + + def test_search_scope(self, ds): + ds.put("number", 22, "general") + ds.put("number", 11, "general.sub") + ds.put("number1", 22, "general.sub") + ds.put("number2", 3, "general.sub.sub") + assert ds.search_scope("general.sub") == ["number", "number1"] + + def test_search_empty_scope(self, ds): + ds.put("number", 22, "general2") + ds.put("number", 11, "general.sub") + with pytest.raises(EmptyScope) as e: + ds.search_scope("general.sub2") + assert "Given scope general.sub2 is not part of the data store." in e.value.args[0] + assert "Available scopes are: ['general.sub', 'general2']" in e.value.args[0] + + def test_search_scope_and_all_superiors(self, ds): + ds.put("number", 22, "general") + ds.put("number", 11, "general.sub") + ds.put("number1", 22, "general.sub") + ds.put("number2", 3, "general.sub.sub") + assert ds.search_scope("general.sub", current_scope_only=False) == ["number", "number1"] + assert ds.search_scope("general.sub.sub", current_scope_only=False) == ["number", "number1", "number2"] + -- GitLab