Mercurial > libervia-backend
annotate sat_frontends/jp/cmd_info.py @ 3265:1649bbe8d07e
tools (common/utils): new `recursive_update` method for dicts
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 29 Apr 2020 13:53:00 +0200 |
parents | a10e12dfbda8 |
children | be6d91572633 |
rev | line source |
---|---|
3137 | 1 #!/usr/bin/env python3 |
2 | |
966 | 3 |
4 # jp: a SAT command line tool | |
3136 | 5 # Copyright (C) 2009-2020 Jérôme Poisson (goffi@goffi.org) |
966 | 6 |
7 # This program is free software: you can redistribute it and/or modify | |
8 # it under the terms of the GNU Affero General Public License as published by | |
9 # the Free Software Foundation, either version 3 of the License, or | |
10 # (at your option) any later version. | |
11 | |
12 # This program is distributed in the hope that it will be useful, | |
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 # GNU Affero General Public License for more details. | |
16 | |
17 # You should have received a copy of the GNU Affero General Public License | |
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | |
3028 | 20 from . import base |
966 | 21 from sat.core.i18n import _ |
2346
c903c259402a
jp (info/disco): type selection + output improvments:
Goffi <goffi@goffi.org>
parents:
2343
diff
changeset
|
22 from sat.tools.common.ansi import ANSI as A |
3207
a10e12dfbda8
jp(info): `devices` command first draft:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
23 from sat.tools.common import date_utils, data_format |
2114
dc5d214f0a3b
jp (info/session): added a command to get data on current session
Goffi <goffi@goffi.org>
parents:
1960
diff
changeset
|
24 from sat_frontends.jp.constants import Const as C |
2346
c903c259402a
jp (info/disco): type selection + output improvments:
Goffi <goffi@goffi.org>
parents:
2343
diff
changeset
|
25 from sat_frontends.jp import common |
966 | 26 |
971
8ca5c990ed92
jp: "disco" subcommand, moved into a new "info" subcommand + added "version" subcommand which get software version
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
27 __commands__ = ["Info"] |
8ca5c990ed92
jp: "disco" subcommand, moved into a new "info" subcommand + added "version" subcommand which get software version
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
28 |
966 | 29 |
30 class Disco(base.CommandBase): | |
31 | |
32 def __init__(self, host): | |
2346
c903c259402a
jp (info/disco): type selection + output improvments:
Goffi <goffi@goffi.org>
parents:
2343
diff
changeset
|
33 extra_outputs = {'default': self.default_output} |
3040 | 34 super(Disco, self).__init__( |
35 host, 'disco', use_output='complex', extra_outputs=extra_outputs, | |
36 help=_('service discovery')) | |
966 | 37 |
38 def add_parser_options(self): | |
3028 | 39 self.parser.add_argument("jid", help=_("entity to discover")) |
3040 | 40 self.parser.add_argument( |
41 "-t", "--type", type=str, choices=('infos', 'items', 'both'), default='both', | |
42 help=_("type of data to discover")) | |
3028 | 43 self.parser.add_argument("-n", "--node", default='', help=_("node to use")) |
3040 | 44 self.parser.add_argument( |
45 "-C", "--no-cache", dest='use_cache', action="store_false", | |
46 help=_("ignore cache")) | |
2346
c903c259402a
jp (info/disco): type selection + output improvments:
Goffi <goffi@goffi.org>
parents:
2343
diff
changeset
|
47 |
c903c259402a
jp (info/disco): type selection + output improvments:
Goffi <goffi@goffi.org>
parents:
2343
diff
changeset
|
48 def default_output(self, data): |
3028 | 49 features = data.get('features', []) |
50 identities = data.get('identities', []) | |
51 extensions = data.get('extensions', {}) | |
52 items = data.get('items', []) | |
2346
c903c259402a
jp (info/disco): type selection + output improvments:
Goffi <goffi@goffi.org>
parents:
2343
diff
changeset
|
53 |
c903c259402a
jp (info/disco): type selection + output improvments:
Goffi <goffi@goffi.org>
parents:
2343
diff
changeset
|
54 identities_table = common.Table(self.host, |
c903c259402a
jp (info/disco): type selection + output improvments:
Goffi <goffi@goffi.org>
parents:
2343
diff
changeset
|
55 identities, |
3028 | 56 headers=(_('category'), |
57 _('type'), | |
58 _('name')), | |
2346
c903c259402a
jp (info/disco): type selection + output improvments:
Goffi <goffi@goffi.org>
parents:
2343
diff
changeset
|
59 use_buffer=True) |
c903c259402a
jp (info/disco): type selection + output improvments:
Goffi <goffi@goffi.org>
parents:
2343
diff
changeset
|
60 |
c903c259402a
jp (info/disco): type selection + output improvments:
Goffi <goffi@goffi.org>
parents:
2343
diff
changeset
|
61 extensions_tpl = [] |
3028 | 62 extensions_types = list(extensions.keys()) |
1414
159d16336f87
core, bridge, jp: management of service discovery extensions (XEP-0128)
Goffi <goffi@goffi.org>
parents:
1396
diff
changeset
|
63 extensions_types.sort() |
159d16336f87
core, bridge, jp: management of service discovery extensions (XEP-0128)
Goffi <goffi@goffi.org>
parents:
1396
diff
changeset
|
64 for type_ in extensions_types: |
159d16336f87
core, bridge, jp: management of service discovery extensions (XEP-0128)
Goffi <goffi@goffi.org>
parents:
1396
diff
changeset
|
65 fields = [] |
159d16336f87
core, bridge, jp: management of service discovery extensions (XEP-0128)
Goffi <goffi@goffi.org>
parents:
1396
diff
changeset
|
66 for field in extensions[type_]: |
159d16336f87
core, bridge, jp: management of service discovery extensions (XEP-0128)
Goffi <goffi@goffi.org>
parents:
1396
diff
changeset
|
67 field_lines = [] |
159d16336f87
core, bridge, jp: management of service discovery extensions (XEP-0128)
Goffi <goffi@goffi.org>
parents:
1396
diff
changeset
|
68 data, values = field |
3028 | 69 data_keys = list(data.keys()) |
1414
159d16336f87
core, bridge, jp: management of service discovery extensions (XEP-0128)
Goffi <goffi@goffi.org>
parents:
1396
diff
changeset
|
70 data_keys.sort() |
159d16336f87
core, bridge, jp: management of service discovery extensions (XEP-0128)
Goffi <goffi@goffi.org>
parents:
1396
diff
changeset
|
71 for key in data_keys: |
3028 | 72 field_lines.append(A.color('\t', C.A_SUBHEADER, key, A.RESET, ': ', |
2710
b6e16a89311b
jp (info/disco): better default output for extensions
Goffi <goffi@goffi.org>
parents:
2681
diff
changeset
|
73 data[key])) |
b6e16a89311b
jp (info/disco): better default output for extensions
Goffi <goffi@goffi.org>
parents:
2681
diff
changeset
|
74 if len(values) == 1: |
3028 | 75 field_lines.append(A.color('\t', C.A_SUBHEADER, "value", A.RESET, |
76 ': ', values[0] or (A.BOLD + "UNSET"))) | |
2710
b6e16a89311b
jp (info/disco): better default output for extensions
Goffi <goffi@goffi.org>
parents:
2681
diff
changeset
|
77 elif len(values) > 1: |
3028 | 78 field_lines.append(A.color('\t', C.A_SUBHEADER, "values", A.RESET, |
79 ': ')) | |
2710
b6e16a89311b
jp (info/disco): better default output for extensions
Goffi <goffi@goffi.org>
parents:
2681
diff
changeset
|
80 |
b6e16a89311b
jp (info/disco): better default output for extensions
Goffi <goffi@goffi.org>
parents:
2681
diff
changeset
|
81 for value in values: |
3028 | 82 field_lines.append(A.color('\t - ', A.BOLD, value)) |
83 fields.append('\n'.join(field_lines)) | |
3040 | 84 extensions_tpl.append('{type_}\n{fields}'.format( |
85 type_=type_, | |
86 fields='\n\n'.join(fields))) | |
966 | 87 |
3040 | 88 items_table = common.Table( |
89 self.host, | |
90 items, | |
91 headers=( | |
92 _('entity'), | |
93 _('node'), | |
94 _('name')), | |
95 use_buffer=True) | |
2346
c903c259402a
jp (info/disco): type selection + output improvments:
Goffi <goffi@goffi.org>
parents:
2343
diff
changeset
|
96 |
966 | 97 template = [] |
98 if features: | |
3028 | 99 template.append(A.color(C.A_HEADER, _("Features")) + "\n\n{features}") |
966 | 100 if identities: |
3028 | 101 template.append(A.color(C.A_HEADER, _("Identities")) + "\n\n{identities}") |
2346
c903c259402a
jp (info/disco): type selection + output improvments:
Goffi <goffi@goffi.org>
parents:
2343
diff
changeset
|
102 if extensions: |
3028 | 103 template.append(A.color(C.A_HEADER, _("Extensions")) + "\n\n{extensions}") |
966 | 104 if items: |
3028 | 105 template.append(A.color(C.A_HEADER, _("Items")) + "\n\n{items}") |
966 | 106 |
3040 | 107 print("\n\n".join(template).format( |
108 features = '\n'.join(features), | |
109 identities = identities_table.display().string, | |
110 extensions = '\n'.join(extensions_tpl), | |
111 items = items_table.display().string, | |
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) | |
971
8ca5c990ed92
jp: "disco" subcommand, moved into a new "info" subcommand + added "version" subcommand which get software version
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
134 |
3040 | 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() | |
971
8ca5c990ed92
jp: "disco" subcommand, moved into a new "info" subcommand + added "version" subcommand which get software version
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
168 |
8ca5c990ed92
jp: "disco" subcommand, moved into a new "info" subcommand + added "version" subcommand which get software version
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
169 class Version(base.CommandBase): |
8ca5c990ed92
jp: "disco" subcommand, moved into a new "info" subcommand + added "version" subcommand which get software version
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
170 |
8ca5c990ed92
jp: "disco" subcommand, moved into a new "info" subcommand + added "version" subcommand which get software version
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
171 def __init__(self, host): |
2340
4fd499d14b27
jp (info): fixed help for version and session
Goffi <goffi@goffi.org>
parents:
2151
diff
changeset
|
172 super(Version, self).__init__(host, 'version', help=_('software version')) |
971
8ca5c990ed92
jp: "disco" subcommand, moved into a new "info" subcommand + added "version" subcommand which get software version
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
173 |
8ca5c990ed92
jp: "disco" subcommand, moved into a new "info" subcommand + added "version" subcommand which get software version
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
174 def add_parser_options(self): |
8ca5c990ed92
jp: "disco" subcommand, moved into a new "info" subcommand + added "version" subcommand which get software version
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
175 self.parser.add_argument("jid", type=str, help=_("Entity to request")) |
8ca5c990ed92
jp: "disco" subcommand, moved into a new "info" subcommand + added "version" subcommand which get software version
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
176 |
3040 | 177 async def start(self): |
178 jids = await self.host.check_jids([self.args.jid]) | |
971
8ca5c990ed92
jp: "disco" subcommand, moved into a new "info" subcommand + added "version" subcommand which get software version
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
179 jid = jids[0] |
3040 | 180 try: |
181 data = await self.host.bridge.getSoftwareVersion(jid, self.host.profile) | |
182 except Exception as e: | |
183 self.disp(_(f"error while trying to get version: {e}"), error=True) | |
184 self.host.quit(C.EXIT_BRIDGE_ERRBACK) | |
185 else: | |
186 infos = [] | |
187 name, version, os = data | |
188 if name: | |
189 infos.append(_(f"Software name: {name}")) | |
190 if version: | |
191 infos.append(_(f"Software version: {version}")) | |
192 if os: | |
193 infos.append(_(f"Operating System: {os}")) | |
971
8ca5c990ed92
jp: "disco" subcommand, moved into a new "info" subcommand + added "version" subcommand which get software version
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
194 |
3040 | 195 print("\n".join(infos)) |
196 self.host.quit() | |
971
8ca5c990ed92
jp: "disco" subcommand, moved into a new "info" subcommand + added "version" subcommand which get software version
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
197 |
8ca5c990ed92
jp: "disco" subcommand, moved into a new "info" subcommand + added "version" subcommand which get software version
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
198 |
2114
dc5d214f0a3b
jp (info/session): added a command to get data on current session
Goffi <goffi@goffi.org>
parents:
1960
diff
changeset
|
199 class Session(base.CommandBase): |
dc5d214f0a3b
jp (info/session): added a command to get data on current session
Goffi <goffi@goffi.org>
parents:
1960
diff
changeset
|
200 |
dc5d214f0a3b
jp (info/session): added a command to get data on current session
Goffi <goffi@goffi.org>
parents:
1960
diff
changeset
|
201 def __init__(self, host): |
2600
947c4c4c5c53
jp (info/session): by default, display started as human readable date instead of Unix time
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
202 extra_outputs = {'default': self.default_output} |
3040 | 203 super(Session, self).__init__( |
204 host, 'session', use_output='dict', extra_outputs=extra_outputs, | |
205 help=_('running session')) | |
2114
dc5d214f0a3b
jp (info/session): added a command to get data on current session
Goffi <goffi@goffi.org>
parents:
1960
diff
changeset
|
206 |
3040 | 207 def add_parser_options(self): |
208 pass | |
209 | |
210 async def default_output(self, data): | |
2600
947c4c4c5c53
jp (info/session): by default, display started as human readable date instead of Unix time
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
211 started = data['started'] |
3028 | 212 data['started'] = '{short} (UTC, {relative})'.format( |
2605
87f8cf51fca5
jp (info/session): show short + relative date by default for "started"
Goffi <goffi@goffi.org>
parents:
2600
diff
changeset
|
213 short=date_utils.date_fmt(started), |
87f8cf51fca5
jp (info/session): show short + relative date by default for "started"
Goffi <goffi@goffi.org>
parents:
2600
diff
changeset
|
214 relative=date_utils.date_fmt(started, 'relative')) |
3040 | 215 await self.host.output(C.OUTPUT_DICT, 'simple', {}, data) |
2114
dc5d214f0a3b
jp (info/session): added a command to get data on current session
Goffi <goffi@goffi.org>
parents:
1960
diff
changeset
|
216 |
3040 | 217 async def start(self): |
218 try: | |
219 data = await self.host.bridge.sessionInfosGet(self.host.profile) | |
220 except Exception as e: | |
221 self.disp(_(f'Error getting session infos: {e}'), error=True) | |
222 self.host.quit(C.EXIT_BRIDGE_ERRBACK) | |
223 else: | |
224 await self.output(data) | |
225 self.host.quit() | |
2114
dc5d214f0a3b
jp (info/session): added a command to get data on current session
Goffi <goffi@goffi.org>
parents:
1960
diff
changeset
|
226 |
dc5d214f0a3b
jp (info/session): added a command to get data on current session
Goffi <goffi@goffi.org>
parents:
1960
diff
changeset
|
227 |
3207
a10e12dfbda8
jp(info): `devices` command first draft:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
228 class Devices(base.CommandBase): |
a10e12dfbda8
jp(info): `devices` command first draft:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
229 |
a10e12dfbda8
jp(info): `devices` command first draft:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
230 def __init__(self, host): |
a10e12dfbda8
jp(info): `devices` command first draft:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
231 super(Devices, self).__init__( |
a10e12dfbda8
jp(info): `devices` command first draft:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
232 host, 'devices', use_output=C.OUTPUT_LIST_DICT, |
a10e12dfbda8
jp(info): `devices` command first draft:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
233 help=_('devices of an entity')) |
a10e12dfbda8
jp(info): `devices` command first draft:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
234 |
a10e12dfbda8
jp(info): `devices` command first draft:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
235 def add_parser_options(self): |
a10e12dfbda8
jp(info): `devices` command first draft:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
236 self.parser.add_argument( |
a10e12dfbda8
jp(info): `devices` command first draft:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
237 "jid", type=str, nargs='?', default='', help=_("Entity to request")) |
a10e12dfbda8
jp(info): `devices` command first draft:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
238 |
a10e12dfbda8
jp(info): `devices` command first draft:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
239 async def start(self): |
a10e12dfbda8
jp(info): `devices` command first draft:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
240 try: |
a10e12dfbda8
jp(info): `devices` command first draft:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
241 data = await self.host.bridge.devicesInfosGet( |
a10e12dfbda8
jp(info): `devices` command first draft:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
242 self.args.jid, self.host.profile) |
a10e12dfbda8
jp(info): `devices` command first draft:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
243 except Exception as e: |
a10e12dfbda8
jp(info): `devices` command first draft:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
244 self.disp(_(f'Error getting devices infos: {e}'), error=True) |
a10e12dfbda8
jp(info): `devices` command first draft:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
245 self.host.quit(C.EXIT_BRIDGE_ERRBACK) |
a10e12dfbda8
jp(info): `devices` command first draft:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
246 else: |
a10e12dfbda8
jp(info): `devices` command first draft:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
247 data = data_format.deserialise(data, type_check=list) |
a10e12dfbda8
jp(info): `devices` command first draft:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
248 await self.output(data) |
a10e12dfbda8
jp(info): `devices` command first draft:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
249 self.host.quit() |
a10e12dfbda8
jp(info): `devices` command first draft:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
250 |
a10e12dfbda8
jp(info): `devices` command first draft:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
251 |
971
8ca5c990ed92
jp: "disco" subcommand, moved into a new "info" subcommand + added "version" subcommand which get software version
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
252 class Info(base.CommandBase): |
3207
a10e12dfbda8
jp(info): `devices` command first draft:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
253 subcommands = (Disco, Version, Session, Devices) |
971
8ca5c990ed92
jp: "disco" subcommand, moved into a new "info" subcommand + added "version" subcommand which get software version
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
254 |
8ca5c990ed92
jp: "disco" subcommand, moved into a new "info" subcommand + added "version" subcommand which get software version
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
255 def __init__(self, host): |
3040 | 256 super(Info, self).__init__( |
257 host, 'info', use_profile=False, | |
258 help=_('Get various pieces of information on entities')) |