Coverage for suhteita/store.py: 96.15%
38 statements
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-04 22:42:46 +00:00
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-04 22:42:46 +00:00
1"""Provide a simple JSON store for event records."""
3import copy
4import datetime as dti
5import json
6import pathlib
7from typing import Dict, Union, no_type_check
9from suhteita import ENCODING, NODE_INDICATOR, STORE, TS_FORMAT_PAYLOADS, Clocking
11TS_FORMAT_STORE = '%Y%m%dT%H%M%S.%fZ'
14@no_type_check
15class Store:
16 @no_type_check
17 def __init__(
18 self, context: Dict[str, Union[str, dti.datetime]], setup: object, folder_path: Union[pathlib.Path, str] = STORE
19 ):
20 self.store = pathlib.Path(folder_path)
21 self.identity = context['identity']
22 self.start_time = context['start_time']
23 self.end_ts = None
24 self.total_secs = 0.0
25 self.node_indicator = NODE_INDICATOR
26 self.store.mkdir(parents=True, exist_ok=True)
27 self.db_name = f'{self.identity}-{self.start_time.strftime(TS_FORMAT_STORE)}-{self.node_indicator}.json'
28 self.rank = 0
29 self.db = {
30 '_meta': {
31 'scenario': context.get('scenario', 'unknown'),
32 'identity': self.identity,
33 'node_indicator': str(self.node_indicator),
34 'target': context.get('target', 'unknown'),
35 'mode': context.get('mode', 'unknown'),
36 'project': context.get('project', 'unknown'),
37 'db_name': self.db_name,
38 'db_path': str(self.store / self.db_name),
39 'start_ts': self.start_time.strftime(TS_FORMAT_PAYLOADS),
40 'total_secs': self.total_secs,
41 'end_ts': self.end_ts,
42 'has_failures_declared': None,
43 'has_failures_detected': None,
44 'setup': copy.deepcopy(setup.__dict__),
45 },
46 'events': [],
47 }
49 @no_type_check
50 def add(self, label: str, ok: bool, clk: Clocking, comment: str = ''):
51 self.rank += 1
52 self.db['events'].append(
53 {
54 'rank': self.rank,
55 'label': label,
56 'ok': ok,
57 'start_ts': clk[0],
58 'duration_usecs': clk[1],
59 'end_ts': clk[2],
60 'comment': comment,
61 }
62 )
64 @no_type_check
65 def dump(self, end_time: dti.datetime, has_failures: bool = False):
66 self.end_time = end_time
67 self.db['_meta']['end_ts'] = self.end_time.strftime(TS_FORMAT_PAYLOADS)
68 self.db['_meta']['total_secs'] = (self.end_time - self.start_time).total_seconds()
69 self.db['_meta']['has_failures_declared'] = has_failures
70 detect_failures = False
71 for event in self.db['events']:
72 if not event['ok']: 72 ↛ 73line 72 didn't jump to line 73, because the condition on line 72 was never true
73 detect_failures = True
74 self.db['_meta']['has_failures_detected'] = detect_failures
75 with open(self.store / self.db_name, 'wt', encoding=ENCODING) as handle:
76 json.dump(self.db, handle)