diff --git a/src/datastore.py b/src/datastore.py index 4b70908dd94cbf6062f31b5da0c3daf6ec92352a..fb1650808a72f2a4d8b6afc10940cd9d14f894ba 100644 --- a/src/datastore.py +++ b/src/datastore.py @@ -31,6 +31,13 @@ class EmptyScope(Exception): class CorrectScope: + """ + This class is used as decorator for all class methods, that have scope in parameters. After decoration, the scope + argument is not required on method call anymore. If no scope parameter is given, this decorator automatically adds + the default scope=`general` to the arguments. Furthermore, calls like `scope=general.sub` are obsolete, because this + decorator adds the prefix `general.` if not provided. Therefore, a call like `scope=sub` will actually become + `scope=general.sub` after passing this decorator. + """ def __init__(self, func): wraps(func)(self) @@ -42,24 +49,35 @@ class CorrectScope: new_arg = kwargs.pop("scope", "general") or "general" args = self.update_tuple(args, new_arg, pos_scope) else: - args = self.update_tuple(args, self.correct(args[pos_scope]), pos_scope, update=True) + args = self.update_tuple(args, args[pos_scope], pos_scope, update=True) return self.__wrapped__(*args, **kwargs) def __get__(self, instance, cls): - if instance is None: - return self - else: - return types.MethodType(self, instance) + return types.MethodType(self, instance) @staticmethod def correct(arg: str): + """ + adds leading general prefix + :param arg: string argument of scope to add prefix general if necessary + :return: corrected string + """ if not arg.startswith("general"): arg = "general." + arg return arg - @staticmethod - def update_tuple(t, new, ind, update=False): - t_new = (*t[:ind], new, *t[ind + update:]) + def update_tuple(self, t: Tuple, new: Any, ind: int, update: bool = False): + """ + Either updates a entry in given tuple t (<old1>, <old2>, <old3>) --(ind=1)--> (<old1>, <new>, <old3>) or slots + entry into given position (<old1>, <old2>, <old3>) --(ind=1,update=True)--> (<old1>, <new>, <old2>, <old3>). In + the latter case, length of returned tuple is increased by 1 in comparison to given tuple. + :param t: tuple to update + :param new: new element to add to tuple + :param ind: position to add or slot in + :param update: updates entry if true, otherwise slot in (default: False) + :return: updated tuple + """ + t_new = (*t[:ind], self.correct(new), *t[ind + update:]) return t_new diff --git a/test/test_datastore.py b/test/test_datastore.py index 6f454d539e8df49344dd4e8d8440f1abebf815fd..5b6cd17a00271a17b8fe5c30ca26665b42e56141 100644 --- a/test/test_datastore.py +++ b/test/test_datastore.py @@ -4,7 +4,7 @@ __date__ = '2019-11-22' import pytest -from src.datastore import AbstractDataStore, DataStoreByVariable, DataStoreByScope +from src.datastore import AbstractDataStore, DataStoreByVariable, DataStoreByScope, CorrectScope from src.datastore import NameNotFoundInDataStore, NameNotFoundInScope, EmptyScope @@ -324,3 +324,17 @@ class TestDataStoreByScope: ds.set("test2", 4) assert sorted(ds.search_scope(current_scope_only=False)) == sorted(["tester", "test2"]) assert ds.search_scope("sub", current_scope_only=True) == ["tester"] + + +class TestCorrectScope: + + @staticmethod + @CorrectScope + def function1(a, scope, b=44): + return a, scope, b + + def test_init(self): + assert self.function1(22, "general") == (22, "general", 44) + assert self.function1(21) == (21, "general", 44) + assert self.function1(55, "sub", 34) == (55, "general.sub", 34) + assert self.function1("string", b=99, scope="tester") == ("string", "general.tester", 99)