blob: 2038aba9088ebc67bb0036c54ec4c2fc74115bb1 [file] [log] [blame]
Anna Arhipova7cdcc852023-11-15 18:20:45 +01001from parse import parse
Anna Arhipova32dd8ce2024-01-20 15:30:47 +01002from typing import Dict, List, Callable, Any
Anna Arhipova32dd8ce2024-01-20 15:30:47 +01003from django.core.cache import cache
Anna Arhipova7cdcc852023-11-15 18:20:45 +01004
5
6def parse_title(test_name):
7 # Sometimes id can be without the closing ] symbol
8 if "[" in test_name and "]" not in test_name:
9 test_name += "]"
10 token_count = test_name.split(".").__len__()
11
12 if test_name.startswith("=="):
13 return test_name
14
15 if test_name.startswith(".setUp") or test_name.startswith(".tearDown"):
16 fmt = "{test_title}(" + "{}." * (token_count - 2) + "{class_name})"
17 r = parse(fmt, test_name)
18 return f"{r['class_name']}.{r['test_title']}".strip()
19 try:
20 fmt = "{}." * (token_count - 2) + "{class_name}.{test_title}[{id}]"
21 r = parse(fmt, test_name)
22 return f"{r['test_title']}[{r['id']}]"
23 except TypeError:
24 # return file_name.test_class.test_name in other complicated cases
25 return '.'.join(test_name.split(".")[:3])
26
27
28def short_names_for_dict(_dict):
29 __dict = {}
30 for _k in _dict.keys():
31 __k = parse_title(_k)
32 # Replace only those keys which are absent in the dict or empty
33 # (defined as "No result found")
34 if __dict.get(__k) == "No result found" or not __dict.get(__k):
35 __dict[__k] = _dict[_k]
36 return __dict
37
38
39def get_dict_diff(dict1: dict,
40 dict2: dict,
41 compare_by_key=None) -> Dict[str, List]:
42 all_keys = sorted(set(list(dict1.keys()) + list(dict2.keys())))
43
44 result = dict()
45 for k in all_keys:
46 if compare_by_key:
47 if dict1.get(k, {}).get(compare_by_key) == dict2.get(k, {}).get(
48 compare_by_key):
49 continue
50 else:
51 if dict1.get(k) == dict2.get(k):
52 continue
53 result[k] = [dict1.get(k), dict2.get(k)]
54 return result
55
56
Anna Arhipova32dd8ce2024-01-20 15:30:47 +010057def replace_all(text: str, olds: str, new: str) -> str:
58 r = text
59 for _s in olds:
60 r = r.replace(_s, new)
61 return r
62
63
Anna Arhipova14cdf8a2024-02-06 15:43:15 +010064def cached(timeout: int = None,
65 condition_for_endless_cache: Callable = lambda x: False
66 ) -> Callable:
67 """
68 :param timeout: (in seconds) usage accordingly
69 https://docs.djangoproject.com/en/4.2/topics/cache/#basic-usage
70 :param condition_for_endless_cache: Callable should return boolean.
71 Checks a result of function. If Result meets requirements of condition
72 then the endless timeout will be set. Or it will use provided timeout
73 otherwise
74
75 :return: decorator
76 """
Anna Arhipova32dd8ce2024-01-20 15:30:47 +010077 def decorator(func: Callable) -> Callable:
78 def wrapper(*args, **kwargs) -> Any:
79 cache_key = f'{func.__name__}_{args}_{kwargs}'
80 cache_key = replace_all(cache_key, "{}()\'\" .,:", "_")
Anna Arhipova14cdf8a2024-02-06 15:43:15 +010081 cached_value = cache.get(cache_key)
82 if cached_value is None:
Anna Arhipova32dd8ce2024-01-20 15:30:47 +010083 print(f"{func.__name__} MISS")
84 result = func(*args, **kwargs)
Anna Arhipova14cdf8a2024-02-06 15:43:15 +010085 _timeout = None \
86 if condition_for_endless_cache(result) \
87 else timeout
Anna Arhipova32dd8ce2024-01-20 15:30:47 +010088
Anna Arhipova14cdf8a2024-02-06 15:43:15 +010089 cache.set(cache_key, result, timeout=_timeout)
90 return result
Anna Arhipova32dd8ce2024-01-20 15:30:47 +010091 print(f"{func.__name__} hit")
92
93 # # FIXME Assert to test the caching mechanism
94 # _result = func(*args, **kwargs)
95 # for d in difflib.ndiff(str(result), str(_result)):
96 # if not d.startswith(" "):
97 # print(d)
98 # assert result == _result
99 # # ENDFIXME
100
Anna Arhipova14cdf8a2024-02-06 15:43:15 +0100101 return cached_value
Anna Arhipova32dd8ce2024-01-20 15:30:47 +0100102 return wrapper
103 return decorator
104
105
Anna Arhipova7cdcc852023-11-15 18:20:45 +0100106if __name__ == "__main__":
107 pass