|
1 |
| -from collections import OrderedDict |
| 1 | +import threading |
| 2 | +from collections import OrderedDict, defaultdict |
2 | 3 |
|
3 | 4 | from allure_commons.types import AttachmentType
|
4 | 5 | from allure_commons.model2 import ExecutableItem
|
|
8 | 9 | from allure_commons._core import plugin_manager
|
9 | 10 |
|
10 | 11 |
|
| 12 | +class ThreadContextItems: |
| 13 | + |
| 14 | + _thread_context = defaultdict(OrderedDict) |
| 15 | + _init_thread: threading.Thread |
| 16 | + |
| 17 | + @property |
| 18 | + def thread_context(self): |
| 19 | + context = self._thread_context[threading.current_thread()] |
| 20 | + if not context and threading.current_thread() is not self._init_thread: |
| 21 | + uuid, last_item = next(reversed(self._thread_context[self._init_thread].items())) |
| 22 | + context[uuid] = last_item |
| 23 | + return context |
| 24 | + |
| 25 | + def __init__(self, *args, **kwargs): |
| 26 | + self._init_thread = threading.current_thread() |
| 27 | + super().__init__(*args, **kwargs) |
| 28 | + |
| 29 | + def __setitem__(self, key, value): |
| 30 | + self.thread_context.__setitem__(key, value) |
| 31 | + |
| 32 | + def __getitem__(self, item): |
| 33 | + return self.thread_context.__getitem__(item) |
| 34 | + |
| 35 | + def __iter__(self): |
| 36 | + return self.thread_context.__iter__() |
| 37 | + |
| 38 | + def __reversed__(self): |
| 39 | + return self.thread_context.__reversed__() |
| 40 | + |
| 41 | + def get(self, key): |
| 42 | + return self.thread_context.get(key) |
| 43 | + |
| 44 | + def pop(self, key): |
| 45 | + return self.thread_context.pop(key) |
| 46 | + |
| 47 | + def cleanup(self): |
| 48 | + stopped_threads = [] |
| 49 | + for thread in self._thread_context.keys(): |
| 50 | + if not thread.is_alive(): |
| 51 | + stopped_threads.append(thread) |
| 52 | + for thread in stopped_threads: |
| 53 | + del self._thread_context[thread] |
| 54 | + |
| 55 | + |
11 | 56 | class AllureReporter(object):
|
12 | 57 | def __init__(self):
|
13 |
| - self._items = OrderedDict() |
| 58 | + self._items = ThreadContextItems() |
14 | 59 | self._orphan_items = []
|
15 | 60 |
|
16 | 61 | def _update_item(self, uuid, **kwargs):
|
@@ -73,6 +118,7 @@ def get_test(self, uuid):
|
73 | 118 |
|
74 | 119 | def close_test(self, uuid):
|
75 | 120 | test_case = self._items.pop(uuid)
|
| 121 | + self._items.cleanup() |
76 | 122 | plugin_manager.hook.report_result(result=test_case)
|
77 | 123 |
|
78 | 124 | def drop_test(self, uuid):
|
|
0 commit comments