comparison sat_frontends/jp/cmd_info.py @ 3040:fee60f17ebac

jp: jp asyncio port: /!\ this commit is huge. Jp is temporarily not working with `dbus` bridge /!\ This patch implements the port of jp to asyncio, so it is now correctly using the bridge asynchronously, and it can be used with bridges like `pb`. This also simplify the code, notably for things which were previously implemented with many callbacks (like pagination with RSM). During the process, some behaviours have been modified/fixed, in jp and backends, check diff for details.
author Goffi <goffi@goffi.org>
date Wed, 25 Sep 2019 08:56:41 +0200
parents ab2696e34d29
children 9d0df638c8b4
comparison
equal deleted inserted replaced
3039:a1bc34f90fa5 3040:fee60f17ebac
29 29
30 class Disco(base.CommandBase): 30 class Disco(base.CommandBase):
31 31
32 def __init__(self, host): 32 def __init__(self, host):
33 extra_outputs = {'default': self.default_output} 33 extra_outputs = {'default': self.default_output}
34 super(Disco, self).__init__(host, 'disco', use_output='complex', extra_outputs=extra_outputs, help=_('service discovery')) 34 super(Disco, self).__init__(
35 self.need_loop=True 35 host, 'disco', use_output='complex', extra_outputs=extra_outputs,
36 help=_('service discovery'))
36 37
37 def add_parser_options(self): 38 def add_parser_options(self):
38 self.parser.add_argument("jid", help=_("entity to discover")) 39 self.parser.add_argument("jid", help=_("entity to discover"))
39 self.parser.add_argument("-t", "--type", type=str, choices=('infos', 'items', 'both'), default='both', help=_("type of data to discover")) 40 self.parser.add_argument(
41 "-t", "--type", type=str, choices=('infos', 'items', 'both'), default='both',
42 help=_("type of data to discover"))
40 self.parser.add_argument("-n", "--node", default='', help=_("node to use")) 43 self.parser.add_argument("-n", "--node", default='', help=_("node to use"))
41 self.parser.add_argument("-C", "--no-cache", dest='use_cache', action="store_false", help=_("ignore cache")) 44 self.parser.add_argument(
42 45 "-C", "--no-cache", dest='use_cache', action="store_false",
43 def start(self): 46 help=_("ignore cache"))
44 self.get_infos = self.args.type in ('infos', 'both')
45 self.get_items = self.args.type in ('items', 'both')
46 jids = self.host.check_jids([self.args.jid])
47 jid = jids[0]
48 if not self.get_infos:
49 self.gotInfos(None, jid)
50 else:
51 self.host.bridge.discoInfos(jid, node=self.args.node, use_cache=self.args.use_cache, profile_key=self.host.profile, callback=lambda infos: self.gotInfos(infos, jid), errback=self.error)
52
53 def error(self, failure):
54 print((_("Error while doing discovery [%s]") % failure))
55 self.host.quit(1)
56
57 def gotInfos(self, infos, jid):
58 if not self.get_items:
59 self.gotItems(infos, None)
60 else:
61 self.host.bridge.discoItems(jid, node=self.args.node, use_cache=self.args.use_cache, profile_key=self.host.profile, callback=lambda items: self.gotItems(infos, items), errback=self.error)
62
63 def gotItems(self, infos, items):
64 data = {}
65
66 if self.get_infos:
67 features, identities, extensions = infos
68 features.sort()
69 identities.sort(key=lambda identity: identity[2])
70 data.update({
71 'features': features,
72 'identities': identities,
73 'extensions': extensions})
74
75 if self.get_items:
76 items.sort(key=lambda item: item[2])
77 data['items'] = items
78
79 self.output(data)
80 self.host.quit()
81 47
82 def default_output(self, data): 48 def default_output(self, data):
83 features = data.get('features', []) 49 features = data.get('features', [])
84 identities = data.get('identities', []) 50 identities = data.get('identities', [])
85 extensions = data.get('extensions', {}) 51 extensions = data.get('extensions', {})
113 ': ')) 79 ': '))
114 80
115 for value in values: 81 for value in values:
116 field_lines.append(A.color('\t - ', A.BOLD, value)) 82 field_lines.append(A.color('\t - ', A.BOLD, value))
117 fields.append('\n'.join(field_lines)) 83 fields.append('\n'.join(field_lines))
118 extensions_tpl.append('{type_}\n{fields}'.format(type_=type_, 84 extensions_tpl.append('{type_}\n{fields}'.format(
119 fields='\n\n'.join(fields))) 85 type_=type_,
120 86 fields='\n\n'.join(fields)))
121 items_table = common.Table(self.host, 87
122 items, 88 items_table = common.Table(
123 headers=(_('entity'), 89 self.host,
124 _('node'), 90 items,
125 _('name')), 91 headers=(
126 use_buffer=True) 92 _('entity'),
93 _('node'),
94 _('name')),
95 use_buffer=True)
127 96
128 template = [] 97 template = []
129 if features: 98 if features:
130 template.append(A.color(C.A_HEADER, _("Features")) + "\n\n{features}") 99 template.append(A.color(C.A_HEADER, _("Features")) + "\n\n{features}")
131 if identities: 100 if identities:
133 if extensions: 102 if extensions:
134 template.append(A.color(C.A_HEADER, _("Extensions")) + "\n\n{extensions}") 103 template.append(A.color(C.A_HEADER, _("Extensions")) + "\n\n{extensions}")
135 if items: 104 if items:
136 template.append(A.color(C.A_HEADER, _("Items")) + "\n\n{items}") 105 template.append(A.color(C.A_HEADER, _("Items")) + "\n\n{items}")
137 106
138 print("\n\n".join(template).format(features = '\n'.join(features), 107 print("\n\n".join(template).format(
139 identities = identities_table.display().string, 108 features = '\n'.join(features),
140 extensions = '\n'.join(extensions_tpl), 109 identities = identities_table.display().string,
141 items = items_table.display().string, 110 extensions = '\n'.join(extensions_tpl),
142 )) 111 items = items_table.display().string,
143 112 ))
113
114 async def start(self):
115 infos_requested = self.args.type in ('infos', 'both')
116 items_requested = self.args.type in ('items', 'both')
117 jids = await self.host.check_jids([self.args.jid])
118 jid = jids[0]
119
120 # infos
121 if not infos_requested:
122 infos = None
123 else:
124 try:
125 infos = await self.host.bridge.discoInfos(
126 jid,
127 node=self.args.node,
128 use_cache=self.args.use_cache,
129 profile_key=self.host.profile
130 )
131 except Exception as e:
132 self.disp(_(f"error while doing discovery: {e}"), error=True)
133 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
134
135 # items
136 if not items_requested:
137 items = None
138 else:
139 try:
140 items = await self.host.bridge.discoItems(
141 jid,
142 node=self.args.node,
143 use_cache=self.args.use_cache,
144 profile_key=self.host.profile
145 )
146 except Exception as e:
147 self.disp(_(f"error while doing discovery: {e}"), error=True)
148 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
149
150 # output
151 data = {}
152
153 if infos_requested:
154 features, identities, extensions = infos
155 features.sort()
156 identities.sort(key=lambda identity: identity[2])
157 data.update({
158 'features': features,
159 'identities': identities,
160 'extensions': extensions})
161
162 if items_requested:
163 items.sort(key=lambda item: item[2])
164 data['items'] = items
165
166 await self.output(data)
167 self.host.quit()
144 168
145 class Version(base.CommandBase): 169 class Version(base.CommandBase):
146 170
147 def __init__(self, host): 171 def __init__(self, host):
148 super(Version, self).__init__(host, 'version', help=_('software version')) 172 super(Version, self).__init__(host, 'version', help=_('software version'))
149 self.need_loop=True
150 173
151 def add_parser_options(self): 174 def add_parser_options(self):
152 self.parser.add_argument("jid", type=str, help=_("Entity to request")) 175 self.parser.add_argument("jid", type=str, help=_("Entity to request"))
153 176
154 def start(self): 177 async def start(self):
155 jids = self.host.check_jids([self.args.jid]) 178 jids = await self.host.check_jids([self.args.jid])
156 jid = jids[0] 179 jid = jids[0]
157 self.host.bridge.getSoftwareVersion(jid, self.host.profile, callback=self.gotVersion, errback=self.error) 180 try:
158 181 data = await self.host.bridge.getSoftwareVersion(jid, self.host.profile)
159 def error(self, failure): 182 except Exception as e:
160 print((_("Error while trying to get version [%s]") % failure)) 183 self.disp(_(f"error while trying to get version: {e}"), error=True)
161 self.host.quit(1) 184 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
162 185 else:
163 def gotVersion(self, data): 186 infos = []
164 infos = [] 187 name, version, os = data
165 name, version, os = data 188 if name:
166 if name: 189 infos.append(_(f"Software name: {name}"))
167 infos.append(_("Software name: %s") % name) 190 if version:
168 if version: 191 infos.append(_(f"Software version: {version}"))
169 infos.append(_("Software version: %s") % version) 192 if os:
170 if os: 193 infos.append(_(f"Operating System: {os}"))
171 infos.append(_("Operating System: %s") % os) 194
172 195 print("\n".join(infos))
173 print("\n".join(infos)) 196 self.host.quit()
174 self.host.quit()
175 197
176 198
177 class Session(base.CommandBase): 199 class Session(base.CommandBase):
178 200
179 def __init__(self, host): 201 def __init__(self, host):
180 extra_outputs = {'default': self.default_output} 202 extra_outputs = {'default': self.default_output}
181 super(Session, self).__init__(host, 'session', use_output='dict', extra_outputs=extra_outputs, help=_('running session')) 203 super(Session, self).__init__(
182 self.need_loop=True 204 host, 'session', use_output='dict', extra_outputs=extra_outputs,
183 205 help=_('running session'))
184 def default_output(self, data): 206
207 def add_parser_options(self):
208 pass
209
210 async def default_output(self, data):
185 started = data['started'] 211 started = data['started']
186 data['started'] = '{short} (UTC, {relative})'.format( 212 data['started'] = '{short} (UTC, {relative})'.format(
187 short=date_utils.date_fmt(started), 213 short=date_utils.date_fmt(started),
188 relative=date_utils.date_fmt(started, 'relative')) 214 relative=date_utils.date_fmt(started, 'relative'))
189 self.host.output(C.OUTPUT_DICT, 'simple', {}, data) 215 await self.host.output(C.OUTPUT_DICT, 'simple', {}, data)
190 216
191 def add_parser_options(self): 217 async def start(self):
192 pass 218 try:
193 219 data = await self.host.bridge.sessionInfosGet(self.host.profile)
194 def start(self): 220 except Exception as e:
195 self.host.bridge.sessionInfosGet(self.host.profile, callback=self._sessionInfoGetCb, errback=self._sessionInfoGetEb) 221 self.disp(_(f'Error getting session infos: {e}'), error=True)
196 222 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
197 def _sessionInfoGetCb(self, data): 223 else:
198 self.output(data) 224 await self.output(data)
199 self.host.quit() 225 self.host.quit()
200
201 def _sessionInfoGetEb(self, error_data):
202 self.disp(_('Error getting session infos: {}').format(error_data), error=True)
203 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
204 226
205 227
206 class Info(base.CommandBase): 228 class Info(base.CommandBase):
207 subcommands = (Disco, Version, Session) 229 subcommands = (Disco, Version, Session)
208 230
209 def __init__(self, host): 231 def __init__(self, host):
210 super(Info, self).__init__(host, 'info', use_profile=False, help=_('Get various pieces of information on entities')) 232 super(Info, self).__init__(
233 host, 'info', use_profile=False,
234 help=_('Get various pieces of information on entities'))