This repository has been archived by the owner on Feb 16, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 12
/
msginfo.py
177 lines (144 loc) · 4.96 KB
/
msginfo.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
import json
from typing import Dict, Iterable, List
import wrapt
from toolz import groupby, valmap
from jigu.core import StdMsg
from jigu.query.event import EventsQuery
from jigu.util.pretty import PrettyPrintable, see
from jigu.util.serdes import JiguBox
from jigu.util.validation import Schemas as S
__all__ = ["MsgInfo", "MsgInfosQuery"]
class MsgInfo(wrapt.ObjectProxy):
__schema__ = S.OBJECT(
msg_index=S.INTEGER,
success=S.BOOLEAN,
log=S.STRING,
events=S.ARRAY(
S.OBJECT(
type=S.STRING,
attributes=S.ARRAY(S.OBJECT(key=S.STRING, value=S.STRING)),
)
),
)
def __init__(self, msg: StdMsg, success: bool, log: dict, events: EventsQuery):
wrapt.ObjectProxy.__init__(self, msg)
try:
log = json.loads(log)
if type(log) == dict:
log = JiguBox(log)
except:
log = None
self._self_success = success
self._self_log = log
self._self_events = events
self._self_pretty_data = None
@property
def success(self):
return self._self_success
@property
def log(self):
return self._self_log
@property
def events(self):
return self._self_events
def __eq__(self, other):
return (
isinstance(other, MsgInfo)
and self.success == other.success
and self.log == other.log
and self.events == other.events
)
def __ne__(self, other):
# we have to do this because objectproxy uses the underlying wrapped's __neq__
return not self == other
@property
def pretty_data(self):
d = dict(self.__dict__)
items = list(d.items())
items.append(("success", self.success))
if self.log:
items.append(("log", self.log))
items.append(("events", self.events))
return items
def _pretty_output(self, path: str = ""):
return PrettyPrintable._pretty_output(self, path)
def _pretty_repr_(self, path: str = "") -> str:
return PrettyPrintable._pretty_repr_(self, path)
@property
def _pp(self):
"""Shortcut for seeing pretty-printing output."""
see(self)
return None
class MsgInfosQuery(PrettyPrintable):
"""Convenience query structure around a list of MsgInfo objects.
Use the variable name "msgs" if possible.
msgs[n] (n = int) --> n-th MsgInfo
msgs["msg-type / msg-action"] --> recursive query of MsgInfos of that type / action
msgs.msg_action --> list of msginfos of that action
for e in msgs: --> iterate over msginfos
"send" in msgs: --> whether msgs of this action are in collection
"""
def __init__(self, msginfos: Iterable[MsgInfo]):
self.msginfos = list(msginfos)
def __repr__(self) -> str:
r = ", ".join(f"{t}: {n}" for t, n in self.actions.items())
if r == "":
r = "(empty)"
return f"<MsgInfosQuery {r}>"
def __getitem__(self, key):
if isinstance(key, int):
return self.msginfos[key]
if isinstance(key, slice):
return MsgInfosQuery(self.msginfos[key])
elif isinstance(key, str):
return MsgInfosQuery(
[m for m in self.msginfos if m.type == key or m.action == key]
)
elif hasattr(key, "type") and hasattr(key, "action"):
return MsgInfosQuery(
[
m
for m in self.msginfos
if m.type == key.type and m.action == key.action
]
)
else:
return self.msginfos[key]
def __getattr__(self, name):
return self[name]
def __iter__(self):
return iter(self.msginfos)
def __contains__(self, item):
if isinstance(item, StdMsg):
return item.type in self.types
else:
return item in self.types or self.actions
@property
def logs(self) -> List[JiguBox]:
msg_logs = [m.log for m in self.msginfos if m.log is not None]
return msg_logs
@property
def events(self) -> EventsQuery:
msg_events = [event for m in self.msginfos for event in m.events]
return EventsQuery(msg_events)
@property
def types(self) -> Dict[str, int]:
msg_types = groupby(lambda m: m.type, self.msginfos)
msg_types = valmap(len, msg_types)
return msg_types
@property
def actions(self) -> Dict[str, int]:
msg_actions = groupby(lambda m: m.action, self.msginfos)
msg_actions = valmap(len, msg_actions)
return msg_actions
def __len__(self) -> int:
return len(self.msginfos)
# TODO: add printing mechanism?
# Example:
# a = JiguBox({ x: MsgInfo(...) })
# print(a)
@property
def pretty_data(self):
items = groupby(lambda m: str(m.__class__.__name__), self.msginfos)
items = valmap(len, items)
return items.items()