blob: 6c41f58c15ec9b75bd2ac5a58e9390019e643ae4 [file] [log] [blame]
stavrovska28772bc2024-05-22 09:33:50 +02001from typing import Any, Callable, Dict, List
2
Anna Arhipova32dd8ce2024-01-20 15:30:47 +01003from django.core.cache import cache
stavrovska28772bc2024-05-22 09:33:50 +02004from parse import parse
Anna Arhipova7cdcc852023-11-15 18:20:45 +01005
6
7def parse_title(test_name):
8 # Sometimes id can be without the closing ] symbol
9 if "[" in test_name and "]" not in test_name:
10 test_name += "]"
11 token_count = test_name.split(".").__len__()
12
13 if test_name.startswith("=="):
14 return test_name
15
16 if test_name.startswith(".setUp") or test_name.startswith(".tearDown"):
17 fmt = "{test_title}(" + "{}." * (token_count - 2) + "{class_name})"
18 r = parse(fmt, test_name)
19 return f"{r['class_name']}.{r['test_title']}".strip()
20 try:
21 fmt = "{}." * (token_count - 2) + "{class_name}.{test_title}[{id}]"
22 r = parse(fmt, test_name)
23 return f"{r['test_title']}[{r['id']}]"
24 except TypeError:
25 # return file_name.test_class.test_name in other complicated cases
stavrovska28772bc2024-05-22 09:33:50 +020026 return ".".join(test_name.split(".")[:3])
Anna Arhipova7cdcc852023-11-15 18:20:45 +010027
28
29def short_names_for_dict(_dict):
30 __dict = {}
31 for _k in _dict.keys():
32 __k = parse_title(_k)
33 # Replace only those keys which are absent in the dict or empty
34 # (defined as "No result found")
35 if __dict.get(__k) == "No result found" or not __dict.get(__k):
36 __dict[__k] = _dict[_k]
37 return __dict
38
39
stavrovska28772bc2024-05-22 09:33:50 +020040def get_dict_diff(
41 dict1: dict, dict2: dict, compare_by_key=None
42) -> Dict[str, List]:
Anna Arhipova7cdcc852023-11-15 18:20:45 +010043 all_keys = sorted(set(list(dict1.keys()) + list(dict2.keys())))
44
45 result = dict()
46 for k in all_keys:
47 if compare_by_key:
48 if dict1.get(k, {}).get(compare_by_key) == dict2.get(k, {}).get(
stavrovska28772bc2024-05-22 09:33:50 +020049 compare_by_key
50 ):
Anna Arhipova7cdcc852023-11-15 18:20:45 +010051 continue
52 else:
53 if dict1.get(k) == dict2.get(k):
54 continue
55 result[k] = [dict1.get(k), dict2.get(k)]
56 return result
57
58
Anna Arhipova32dd8ce2024-01-20 15:30:47 +010059def replace_all(text: str, olds: str, new: str) -> str:
60 r = text
61 for _s in olds:
62 r = r.replace(_s, new)
63 return r
64
65
stavrovska28772bc2024-05-22 09:33:50 +020066def cached(
67 timeout: int = None,
68 condition_for_endless_cache: Callable = lambda x: False,
69) -> Callable:
Anna Arhipova14cdf8a2024-02-06 15:43:15 +010070 """
71 :param timeout: (in seconds) usage accordingly
72 https://docs.djangoproject.com/en/4.2/topics/cache/#basic-usage
73 :param condition_for_endless_cache: Callable should return boolean.
74 Checks a result of function. If Result meets requirements of condition
75 then the endless timeout will be set. Or it will use provided timeout
76 otherwise
77
78 :return: decorator
79 """
stavrovska28772bc2024-05-22 09:33:50 +020080
Anna Arhipova32dd8ce2024-01-20 15:30:47 +010081 def decorator(func: Callable) -> Callable:
82 def wrapper(*args, **kwargs) -> Any:
stavrovska28772bc2024-05-22 09:33:50 +020083 cache_key = f"{func.__name__}_{args}_{kwargs}"
84 cache_key = replace_all(cache_key, "{}()'\" .,:", "_")
Anna Arhipova14cdf8a2024-02-06 15:43:15 +010085 cached_value = cache.get(cache_key)
86 if cached_value is None:
Anna Arhipova32dd8ce2024-01-20 15:30:47 +010087 print(f"{func.__name__} MISS")
88 result = func(*args, **kwargs)
stavrovska28772bc2024-05-22 09:33:50 +020089 _timeout = (
90 None if condition_for_endless_cache(result) else timeout
91 )
Anna Arhipova32dd8ce2024-01-20 15:30:47 +010092
Anna Arhipova14cdf8a2024-02-06 15:43:15 +010093 cache.set(cache_key, result, timeout=_timeout)
94 return result
Anna Arhipova32dd8ce2024-01-20 15:30:47 +010095 print(f"{func.__name__} hit")
96
97 # # FIXME Assert to test the caching mechanism
98 # _result = func(*args, **kwargs)
99 # for d in difflib.ndiff(str(result), str(_result)):
100 # if not d.startswith(" "):
101 # print(d)
102 # assert result == _result
103 # # ENDFIXME
104
Anna Arhipova14cdf8a2024-02-06 15:43:15 +0100105 return cached_value
stavrovska28772bc2024-05-22 09:33:50 +0200106
Anna Arhipova32dd8ce2024-01-20 15:30:47 +0100107 return wrapper
stavrovska28772bc2024-05-22 09:33:50 +0200108
Anna Arhipova32dd8ce2024-01-20 15:30:47 +0100109 return decorator
110
111
Anna Arhipova7cdcc852023-11-15 18:20:45 +0100112if __name__ == "__main__":
113 pass